Maven-metadata.xml created for non-unique SNAPSHOT artifacts

When unique versions are disabled via the MavenDeployer#setUniqueVersion(boolean) method, a maven-metadata.xml file is still created which later causes problems with resolution when Gradle reads the metadata and then tries to incorrectly search for an artifact with a unique version name.

A problem occurred configuring root project ‘TextWrapping’.

Could not resolve all dependencies for configuration ‘:_debugCompile’.
Could not find com.android.support:support-v4:23.0.0-SNAPSHOT.
Searched in the following locations:
file:/Volumes/Android/Projects/utils-fullsdk-mac/extras/android/m2repository/com/android/support/support-v4/23.0.0-SNAPSHOT/maven-metadata.xml
file:/Volumes/Android/Projects/utils-fullsdk-mac/extras/android/m2repository/com/android/support/support-v4/23.0.0-SNAPSHOT/support-v4-23.0.0-20160105.155822-1.pom
file:/Volumes/Android/Projects/utils-fullsdk-mac/extras/android/m2repository/com/android/support/support-v4/23.0.0-SNAPSHOT/support-v4-23.0.0-20160105.155822-1.jar
Required by:
:TextWrapping:unspecified

If unique versions are not used when publishing SNAPSHOT artifacts then no maven-metadata.xml file should be created.

Setting uniqueVersion to false in newer Gradle versions is effectively broken due to the upgrade to Maven 3 libraries internally. Maven simply dropped support for this feature in Maven 3. I expect we should probably do the same since it’s busted as is. I’ve raised GRADLE-3387 to track this.

Doesn’t Gradle still produce a Maven 2 compatible repository even though it’s using Maven 3 internally? Using the maven.metadata.legacy property?

Looking at the AbstractMavenPublishAction source, it looks like the SNAPSHOT metadata files may be produced by the SnapshotMetadataGeneratorFactory which is added as a generator:

private RepositorySystem newRepositorySystem() {
    try {
        DefaultDeployer deployer = (DefaultDeployer) getContainer().lookup(Deployer.class);
        // This is a workaround for https://issues.gradle.org/browse/GRADLE-3324.
        // Somehow the ArrayList 'result' in `org.sonatype.aether.impl.internal.Utils#sortMetadataGeneratorFactories` ends up
        // being a list of nulls on windows and IBM's 1.6 JDK.
        deployer.setMetadataFactories(null);
        deployer.addMetadataGeneratorFactory(new VersionsMetadataGeneratorFactory());
        deployer.addMetadataGeneratorFactory(new SnapshotMetadataGeneratorFactory());
        deployer.addMetadataGeneratorFactory(snapshotVersionManager);
        return container.lookup(RepositorySystem.class);
    } catch (ComponentLookupException e) {
        throw UncheckedException.throwAsUncheckedException(e);
    }
}

I was able to workaround the issue for now by manually deleting the maven-metadata.xml* files from the repo after uploading the artifacts:

doLast {
    // Remove any invalid maven-metadata.xml files that may have been created
    // for SNAPSHOT versions that are *not* uniquely versioned.
    pom*.each { pom ->
        if (pom.version.endsWith('-SNAPSHOT')) {
            final File artifactDir = new File(rootProject.ext.supportRepoOut,
                    pom.groupId.replace('.', '/')
                    + '/' + pom.artifactId
                    + '/' + pom.version)
            delete fileTree(dir: artifactDir, include: 'maven-metadata.xml*')
        }
    }
}

This doesn’t affect unique snapshots unfortunately. Maven 3 simply doesn’t have the capability to omit this data from metadata.

https://cwiki.apache.org/confluence/display/MAVEN/Maven+3.x+Compatibility+Notes#Maven3.xCompatibilityNotes-Non-uniqueSnapshotDeployments

Hmm that’s true, but isn’t Gradle still the one creating those files in the AbstractMavenPublishAction?

Non-unique snapshots are generally a bad idea, but since my maven repo is checked into a VCS system using them makes overwriting/deleting old SNAPSHOTs a major pain.

Nope, this is delegated to Maven.

https://github.com/gradle/gradle/blob/master/subprojects/maven/src/main/groovy/org/gradle/api/publication/maven/internal/action/AbstractMavenPublishAction.java#L130-L131

Right but it could not register the SnapshotMetadataGeneratorFactory when uniqueVersion is set to to false.

That’s a possibility, however I think it might have side effects for resolving modules from a repo with both release versions and snapshots. In that case someone looking for “latest” wouldn’t see the new snapshot. That is something worth investigating.

From my testing locally, it doesn’t seem to cause any problems. The maven-metadata.xml file that contains the list of versions is still updated correctly (I assume by the VersionsMetadataGeneratorFactory).