This message was deleted.
# community-support
s
This message was deleted.
j
There is no public API to do that directly. What is your use case? Maybe it can be solved by looking at a resolution result:
Configuration.getIncoming().getResolutionResult()...
You may be able to use the internal parser, but that implementation is more likely to change than the spec itself. The spec has not changed for many months and if, it would change in a backward compatible way, as all
module
files that are already published will stay supported. If you really need it, it might be better to do your own implementation (maybe by copying Gradle's internal impl). In the end, it's "just" JSON.
t
I'm trying to add module support to our offline repository cache downloader. I was able to get this working with an ArtifactView across a whole configuration, however that is only getting the module explicitly declared dependencies, and not the ones added via the module file. And I need the module file for the added transitive dependency as well. So my thought was parse the module files manually and manually add the dependency it declares to the configuration I'm resolving.
Copy code
plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

class DirectMetadataAccessVariantRule implements ComponentMetadataRule {
    @javax.inject.Inject
    ObjectFactory getObjects() { }
    void execute(ComponentMetadataContext context) {
        def id = context.details.id
        context.details.addVariant("withModules") {
            attributes {
                attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION))
                attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, "modules"))
            }
            withFiles {
                addFile("${id.name}-${id.version}.module")
            }
        }
    }
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1'
    components {
        all(DirectMetadataAccessVariantRule)
    }
}
task runThing {
    doLast {
        project.configurations.all {
            if (!it.canBeResolved) {
                return
            }
            def cfg = it
            ArtifactView view = cfg.getIncoming().artifactView(viewConfiguration -> {
                viewConfiguration.withVariantReselection()
                viewConfiguration.lenient = false
                viewConfiguration.attributes(attributeContainer -> {
                    attributeContainer.attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, "modules"));
                });
            });
            view.files.each {
                println it
            }
        }
    }
}
I have the above project. It gives the following output
Copy code
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.junit.jupiter\junit-jupiter-params\5.10.1\7ac458fdf1c7f6b8be394b547c4313eac4744cd3\junit-jupiter-params-5.10.1.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.junit.jupiter\junit-jupiter-api\5.10.1\ccccfac2d69b33f5063ac4b221dd7ceefa9a45b2\junit-jupiter-api-5.10.1.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.junit.platform\junit-platform-commons\1.10.1\f0ee9d51e8b2ebaf9520b99a96004d10aa92f8bd\junit-platform-commons-1.10.1.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.junit.jupiter\junit-jupiter\5.10.1\447d621f84853f664d8e03784b46b17e440ff101\junit-jupiter-5.10.1.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.opentest4j\opentest4j\1.3.0\58a4564bc6cdb80b8e1d907a61f6e5bd80f6e67\opentest4j-1.3.0.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.apiguardian\apiguardian-api\1.1.2\3926494c1a91787100e2ad2dac7436cb444b85a6\apiguardian-api-1.1.2.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.junit.jupiter\junit-jupiter-params\5.10.1\7ac458fdf1c7f6b8be394b547c4313eac4744cd3\junit-jupiter-params-5.10.1.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.junit.jupiter\junit-jupiter-engine\5.10.1\e22648d96c56472203e72ca244f45ceb3419edef\junit-jupiter-engine-5.10.1.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.junit.jupiter\junit-jupiter-api\5.10.1\ccccfac2d69b33f5063ac4b221dd7ceefa9a45b2\junit-jupiter-api-5.10.1.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.junit.platform\junit-platform-engine\1.10.1\cbc98eac6479474db3151f363f19dfed589cc9d0\junit-platform-engine-1.10.1.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.junit.platform\junit-platform-commons\1.10.1\f0ee9d51e8b2ebaf9520b99a96004d10aa92f8bd\junit-platform-commons-1.10.1.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.junit.jupiter\junit-jupiter\5.10.1\447d621f84853f664d8e03784b46b17e440ff101\junit-jupiter-5.10.1.module
C:\Users\thadh\.gradle\caches\modules-2\files-2.1\org.opentest4j\opentest4j\1.3.0\58a4564bc6cdb80b8e1d907a61f6e5bd80f6e67\opentest4j-1.3.0.module
This grabs all the modules for everything explicitly declared. However, junit-jupiter loads junit-bom using the gradle module file for junit-jupiter, and I need to be able to grab the module file for junit-bom as well.
Basically I need a way to grab everything needed to build an offline dependency cache for a project. And I can't use gradles stock read only cache support because I don't control the environment on the target systems (Plus I don't trust gradles caching at all after the deletion changes they made years ago)
j
I think you are on the right track. There is another
addVariant
or
maybeAddVariant
method that allows you to inherit everything from an existing variant. That way, you can have your
withModules
variant based on the
runtimeElements
or
runtime
variant (the name differs depending on whether there is a
.module
or only a
.pom
file). Then you get everything transitive:
Copy code
context.details.maybeAddVariant("withModules", "runtimeElements") {
   ...
}
context.details.maybeAddVariant("withModules", "runtime") {
   ...
}
I have a very similar example here: https://github.com/jjohannes/gradle-demos/blob/main/variants-with-additional-artif[…]example/gradle/metadatarules/DirectMetadataAccessVariantRule.kt If you only want the metadata, you may have to a
removeAllFiles()
in the
withFiles
section. Maybe this already solves your use case?
t
That doesn't seem to fully work. It's not grabbing junit-bom.
Copy code
plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

class DirectMetadataAccessVariantRule implements ComponentMetadataRule {
    @javax.inject.Inject
    ObjectFactory getObjects() { }
    void execute(ComponentMetadataContext context) {
        def id = context.details.id
        context.details.addVariant("moduleMetadata") {
            attributes {
                attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
                attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION))
                attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, "gradle-module-metadata"))
            }
            withFiles {
                removeAllFiles()
                addFile("${id.name}-${id.version}.module")
            }
        }
        context.details.addVariant("allFiles") {
            attributes {
                attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
                attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION))
                attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, "all-files"))
            }
            withFiles {
                addFile("${id.name}-${id.version}.pom")
                addFile("${id.name}-${id.version}.module")
            }
        }
        context.details.maybeAddVariant("allFilesWithDependenciesElements", "runtimeElements") {
            attributes {
                attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
                attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION))
                attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, "all-files-with-dependencies"))
            }
            withFiles {
                removeAllFiles()
                addFile("${id.name}-${id.version}.pom")
                addFile("${id.name}-${id.version}.module")
            }
        }
        context.details.maybeAddVariant("allFilesWithDependencies", "runtime") {
            attributes {
                attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
                attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION))
                attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, "all-files-with-dependencies"))
            }
            withFiles {
                removeAllFiles()
                addFile("${id.name}-${id.version}.pom")
                addFile("${id.name}-${id.version}.module")
            }
        }
    }
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    components {
        all(DirectMetadataAccessVariantRule)
    }
}
task runThing {
    doLast {
        project.configurations.all {
            if (!it.canBeResolved) {
                return
            }
            def cfg = it
            ArtifactView view = cfg.getIncoming().artifactView(viewConfiguration -> {
                viewConfiguration.withVariantReselection()
                viewConfiguration.lenient = true
                viewConfiguration.attributes(attributeContainer -> {
                    attributeContainer.attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, "all-files-with-dependencies"));
                });
            });
            view.files.each {
                println it
            }
        }
    }
}
I think part of it might be because the dependency is purely a module dependency. https://repo.maven.apache.org/maven2/org/junit/jupiter/junit-jupiter/5.10.1/junit-jupiter-5.10.1.module
Copy code
{
                    "group": "org.junit",
                    "module": "junit-bom",
                    "version": {
                        "requires": "5.10.1"
                    },
                    "attributes": {
                        "org.gradle.category": "platform"
                    },
                    "endorseStrictVersions": true
                },
Is there something about being a platform category that is causing issues?
Ah. I needed to make a variant with a REGULAR_PLATFORM category rather than a DOUCMENTATION category
j
I haven't thought about this interaction when I made the example moths ago. I just used
Category.DOCUMENTATION
because it seemed fitting. I think what I would do today is use one unique USAGE attribute value to not unnecessarily get into these kinds of conflicts:
Copy code
attributes {
                attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.USAGE_ATTRIBUTE, "all-files-with-dependencies"))
            }