I have a scenario which resembles a dependency cycle that causes Gradle to fail when resolving the configuration. Given two modules A and B, which look sorta like this (psuedo Gradle):
name = 'A'
dependencies {
compile 'B'
compile ['C','D','E','F', etc]
}
name = 'B'
dependencies {
testCompile 'A'
}
Technically I don’t consider that cycle, but when resolving B, it will revisit itself in a different config. When resolving B, I can see it visiting the InternalDependencyResult that which representes A(compile)->B(default) in ResolutionResultBuilder.resolvedConfiguration. InternalDependencyResult.selector.module.selected.resolver is null, the selected is for an older B.
I only see this because I’m in the debugger, the stacktrace is below when it goes on to fail. I have no idea is resolver is allowed to be null or not, but getFailure() seems like it assumes that resolver can never be null. I’m guessing the DefaultModuleRevisionResolveState is in a bad state.
I know that cycles are bad, but does Gradle not even support traversing a graph with a cycle? Are there reports of cycle breaking resolution?
java.lang.NullPointerException
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DependencyGraphBuilder$DependencyEdge.getFailure(DependencyGraphBuilder.java:415)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.result.ResolutionResultBuilder.resolvedConfiguration(ResolutionResultBuilder.java:59)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DependencyGraphBuilder.assembleResult(DependencyGraphBuilder.java:167)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DependencyGraphBuilder.resolve(DependencyGraphBuilder.java:72)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultDependencyResolver.resolve(DefaultDependencyResolver.java:78)
at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver$1.create(CacheLockingArtifactDependencyResolver.java:39)
at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver$1.create(CacheLockingArtifactDependencyResolver.java:37)
at org.gradle.cache.internal.DefaultCacheAccess.useCache(DefaultCacheAccess.java:124)
at org.gradle.cache.internal.DefaultPersistentDirectoryStore.useCache(DefaultPersistentDirectoryStore.java:130)
at org.gradle.api.internal.artifacts.ivyservice.DefaultCacheLockingManager.useCache(DefaultCacheLockingManager.java:53)
at org.gradle.api.internal.artifacts.ivyservice.CacheLockingArtifactDependencyResolver.resolve(CacheLockingArtifactDependencyResolver.java:37)
at org.gradle.api.internal.artifacts.ivyservice.SelfResolvingDependencyResolver.resolve(SelfResolvingDependencyResolver.java:41)
at org.gradle.api.internal.artifacts.ivyservice.ShortcircuitEmptyConfigsArtifactDependencyResolver.resolve(ShortcircuitEmptyConfigsArtifactDependencyResolver.java:46)
at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingArtifactDependencyResolver.resolve(ErrorHandlingArtifactDependencyResolver.java:39)
at org.gradle.api.internal.artifacts.ivyservice.DefaultConfigurationResolver.resolve(DefaultConfigurationResolver.java:42)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveNow(DefaultConfiguration.java:240)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$900(DefaultConfiguration.java:45)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationResolvableDependencies.getResolutionResult(DefaultConfiguration.java:564)
at org.gradle.api.tasks.diagnostics.internal.dependencies.AsciiDependencyReportRenderer.render(AsciiDependencyReportRenderer.java:84)
at org.gradle.api.tasks.diagnostics.DependencyReportTask.generate(DependencyReportTask.java:60)
at org.gradle.api.tasks.diagnostics.AbstractReportTask.generate(AbstractReportTask.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)