Cannot resolve an ivy module with custom ivy status

I have a legacy ivy repository where jars were built with a custom ivy status. Is there a way to tell Gradle about accepting a custom ivy status? If I try to pull from this repo, gradle fails with an error message about “bad status”.

I’m afraid there not currently any way to use Gradle’s built-in repository implementations when the contained modules have a custom status.

One way to get it to work would be to use an appropriately configured Ivy DependencyResolver instance: you can see a few examples of these in our integration tests (no other docs, sorry). You can check these out at https://github.com/gradle/gradle/tree/master/subprojects/core-impl/src/integTest/groovy/org/gradle/integtests/resolve/custom.

It appears that org.gradle.api.internal.artifacts.ivyservice.DefaultSettingsConverter.convertForResolve is taking the URLResolver (that I’m creating) and overriding all the settings, which specifically include our custom statuses. The act of calling addResolver is what is setting the IvySettings from IvySettingsFactory. The examples given by Daz don’t cover the settings of IvySettings, they only really set the patterns.

It doesn’t seem possible in 1.4 to set custom statuses.

Right, sorry for the misdirect. When we construct a custom IvySettings instance and add your resolver to it, we effectively overwrite any settings that were configured when the resolver was constructed. So it’s not possibly to update the set of known statuses to use when resolving.

I see 2 ways to tackle this: 1. Use a custom IvyResolver implementation that doesn’t validate the status in an ivy.xml file against the list of known status values. (This code is in org.apache.ivy.plugins.resolver.AbstractResolver) 2. Fix Gradle so that the built-in repository implementations don’t fail if ivy.xml contains an unknown status. (This code is in org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceResolver, which is an inlined copy of the code from AbstractResolver).

If you’re interested in pursuing 2., I’d be happy to help out. This would involve: 1. Removing the code that does the validation (which seems kind of pointless). 2. Adding some integration test coverage for resolving modules with ‘custom’ ivy status.

  • Resolving with a static version (eg 1.0)

  • Resolving with ‘latest.integration’

  • Resolving with ‘latest.custom’

The first step is pretty trivial, and there are good examples of similar tests in org.gradle.integtests.resolve.ivy.IvyDynamicRevisionResolveIntegrationTest. We’d appreciate the contribution.

I’ve raised GRADLE-2715 for this bug.

Thanks for raising an issue.

In both examples, you suggest avoiding validation of the status, except that is exactly what I want to happen. Not only do I want them validated, I need them to be taken into account when resolving dynamic versions, like ‘latest.candidate’ where “candidate” is a custom status. But Ivy needs to know that “candidate” is higher than snapshot and less than release, otherwise it would take status=“snapshot” into account when calculating latest.candidate.

Not that I recommend this hack for general use, since it could break in future versions, but it could come in helpful for someone else:

ProjectInternalServiceRegistry registry = project.services
DefaultDependencyManagementServices depMgmtServices = registry.get(DependencyManagementServices.class)
DefaultModuleDescriptorFactory mdFactory = depMgmtServices.get(ModuleDescriptorFactory.class)
mdFactory.settingsConverter.resolveSettings = IvyHacker.createIvySettings()

Since it is important to be able to define these statuses, I’d recommend that it be baked into the DSL directly, which I understand will take a while, if it’s going to be done at all.

OK understood. I think the original poster had the issue of simply not being able to resolve a module with a custom status. If you actually want to be able to use the ivy statuses in a meaningful way, the problem/solution is more sophisticated.

So “integration” < “milestone” < “release” isn’t sufficient to model your domain? If you can somehow squeeze your requirements into that model, then things should just work.

That is an appropriate model, it’s just not what we already have. We have an existing system with 30,000 modules. It uses snapshot < candidate < release. There’s a direct mapping to the default in Ivy. I just can’t justify changing them to a the more standard scheme, though I am tempted to. It’s more important for Gradle to play nice with the existing Ant code first, then we can look restructuring our statuses.

I’ve raised GRADLE-2716 for the specific issue of handling ranked custom ivy status values when resolving using latest.. This would be a more significant piece of work than GRADLE-2715.

The way we implement GRADLE-2716 may not involve configuring status values in ivy, but instead we might provide a dependency resolve rule where you could influence the process of choosing a selected module, given the module metadata for all available versions.