[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