Skip to content

Instantly share code, notes, and snippets.

@scr
Created May 15, 2017 22:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scr/f3cb1ed67e70c8312c930b8f2f6e826e to your computer and use it in GitHub Desktop.
Save scr/f3cb1ed67e70c8312c930b8f2f6e826e to your computer and use it in GitHub Desktop.
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler
import org.gradle.api.internal.artifacts.repositories.DefaultBaseRepositoryFactory
import org.gradle.util.ConfigureUtil
import java.lang.reflect.Field
/**
* This is the desired behavior, but a fairly gross hack to get it there.
*
* Add a {@code pomfixMaven} method to repositories that adds a repository that will fix instead of barfing
* when the identifier fields don't match the expectations.
*
* @author scr on 5/15/17.
*/
class PomfixMavenArtifactPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
DefaultRepositoryHandler rh = project.repositories
Field repositoryFactoryField = DefaultRepositoryHandler.getDeclaredField('repositoryFactory')
repositoryFactoryField.setAccessible(true)
DefaultBaseRepositoryFactory rf = repositoryFactoryField.get(rh) as DefaultBaseRepositoryFactory
Field instantiatorField = DefaultBaseRepositoryFactory.getDeclaredField('instantiator')
instantiatorField.setAccessible(true)
// Add a method pomfixMaven to the repositories that uses our subclass of the maven repository.
rh.metaClass.pomfixMaven = { Closure closure ->
MavenArtifactRepository af = rf.instantiator.newInstance(PomfixMavenArtifactRepository,
rf.fileResolver, rf.transportFactory, rf.locallyAvailableResourceFinder, rf.instantiator,
rf.artifactFileStore, rf.pomParser, rf.createAuthenticationContainer(), rf.moduleIdentifierFactory)
rh.addRepository(af, 'maven', ConfigureUtil.configureUsing(closure))
}
}
}
import org.gradle.api.InvalidUserDataException
import org.gradle.api.artifacts.repositories.AuthenticationContainer
import org.gradle.api.internal.artifacts.ImmutableModuleIdentifierFactory
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.parser.MetaDataParser
import org.gradle.api.internal.artifacts.repositories.DefaultMavenArtifactRepository
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.file.FileResolver
import org.gradle.internal.component.external.model.ModuleComponentArtifactIdentifier
import org.gradle.internal.component.external.model.ModuleComponentArtifactMetadata
import org.gradle.internal.component.external.model.MutableMavenModuleResolveMetadata
import org.gradle.internal.reflect.Instantiator
import org.gradle.internal.resource.local.FileStore
import org.gradle.internal.resource.local.LocallyAvailableResourceFinder
/**
* Fairly extreme measures to hook into the consistency check in order to repair instead of fail when ids don't match.
*
* @author scr on 5/15/17.
*/
class PomfixMavenArtifactRepository extends DefaultMavenArtifactRepository {
final LocallyAvailableResourceFinder<ModuleComponentArtifactMetadata> myLocallyAvailableResourceFinder
final FileStore<ModuleComponentArtifactIdentifier> myArtifactFileStore
ImmutableModuleIdentifierFactory myModuleIdentifierFactory
PomfixMavenArtifactRepository(
FileResolver fileResolver,
RepositoryTransportFactory transportFactory,
LocallyAvailableResourceFinder<ModuleComponentArtifactMetadata> locallyAvailableResourceFinder,
Instantiator instantiator,
FileStore<ModuleComponentArtifactIdentifier> artifactFileStore,
MetaDataParser<MutableMavenModuleResolveMetadata> pomParser,
AuthenticationContainer authenticationContainer,
ImmutableModuleIdentifierFactory moduleIdentifierFactory) {
super(fileResolver, transportFactory, locallyAvailableResourceFinder, instantiator, artifactFileStore,
pomParser, authenticationContainer, moduleIdentifierFactory)
// Save the private fields we want access to to create a MavenResolver.
myLocallyAvailableResourceFinder = locallyAvailableResourceFinder
myArtifactFileStore = artifactFileStore
myModuleIdentifierFactory = moduleIdentifierFactory
}
/**
* Override this and copy/paste most of the method because createResolver(URI) is private :(
*
* @return
*/
@Override
protected MavenResolver createRealResolver() {
URI rootUri = getUrl();
if (rootUri == null) {
throw new InvalidUserDataException("You must specify a URL for a Maven repository.");
} else {
MavenResolver resolver = createPomfixResolver(rootUri);
artifactUrls.each {
resolver.addArtifactLocation(it);
}
return resolver;
}
}
/**
* Create variant of the createResolver that creates a MavenResolver that has the consistency check overridden.
*
* @param rootUri
* @return
*/
protected MavenResolver createPomfixResolver(URI rootUri) {
RepositoryTransport transport = getTransport(rootUri.getScheme());
new PomfixMavenResolver(getName(), rootUri, transport, myLocallyAvailableResourceFinder, myArtifactFileStore,
pomParser, myModuleIdentifierFactory);
}
}
import groovy.util.logging.Slf4j
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.internal.artifacts.ImmutableModuleIdentifierFactory
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.repositories.resolver.MavenResolver
import org.gradle.api.internal.artifacts.repositories.transport.RepositoryTransport
import org.gradle.internal.component.external.model.ModuleComponentArtifactIdentifier
import org.gradle.internal.component.external.model.ModuleComponentArtifactMetadata
import org.gradle.internal.component.external.model.MutableMavenModuleResolveMetadata
import org.gradle.internal.component.external.model.MutableModuleComponentResolveMetadata
import org.gradle.internal.resource.local.FileStore
import org.gradle.internal.resource.local.LocallyAvailableResourceFinder
/**
* @author scr on 5/15/17.
*/
@Slf4j
class PomfixMavenResolver extends MavenResolver {
PomfixMavenResolver(String name,
URI rootUri,
RepositoryTransport transport,
LocallyAvailableResourceFinder<ModuleComponentArtifactMetadata> locallyAvailableResourceFinder,
FileStore<ModuleComponentArtifactIdentifier> artifactFileStore,
MetaDataParser<MutableMavenModuleResolveMetadata> pomParser,
ImmutableModuleIdentifierFactory moduleIdentifierFactory) {
super(name, rootUri, transport, locallyAvailableResourceFinder, artifactFileStore, pomParser,
moduleIdentifierFactory)
}
@Override
protected void checkMetadataConsistency(ModuleComponentIdentifier expectedId, MutableModuleComponentResolveMetadata metadata) throws MetaDataParseException {
try {
super.checkMetadataConsistency(expectedId, metadata);
} catch (MetaDataParseException ex) {
log.warn("{}; setting to {} to fix.", ex.getLocalizedMessage(), expectedId);
metadata.setComponentId(expectedId);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment