Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,24 @@

package com.google.android.gms.oss.licenses.plugin

import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import java.io.Serializable

/**
* Data class to hold the resolved physical files for a single dependency.
*/
class ArtifactFiles implements Serializable {
@InputFile
@PathSensitive(PathSensitivity.NONE)
@Optional
File pomFile

@InputFile
@PathSensitive(PathSensitivity.NONE)
@Optional
File libraryFile

ArtifactFiles(File pomFile, File libraryFile) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ import groovy.json.JsonBuilder
import groovy.json.JsonGenerator
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import org.slf4j.LoggerFactory

Expand All @@ -37,14 +41,16 @@ import static com.android.tools.build.libraries.metadata.Library.LibraryOneofCas
* If the protobuf is not present (e.g. debug variants) it writes a single
* dependency on the {@link DependencyUtil#ABSENT_ARTIFACT}.
*/
@CacheableTask
abstract class DependencyTask extends DefaultTask {
private static final logger = LoggerFactory.getLogger(DependencyTask.class)

@OutputFile
abstract RegularFileProperty getDependenciesJson()

@InputFile
@org.gradle.api.tasks.Optional
@PathSensitive(PathSensitivity.NONE)
@Optional
abstract RegularFileProperty getLibraryDependenciesReport()

@TaskAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.artifacts.result.ResolvedArtifactResult
import org.gradle.api.provider.Provider
import org.gradle.maven.MavenModule
import org.gradle.maven.MavenPomArtifact

Expand All @@ -45,52 +46,54 @@ class DependencyUtil {
*
* @param project The Gradle project used to create the resolution query.
* @param runtimeConfiguration The configuration whose dependencies should be resolved.
* @return A map of GAV coordinates to their resolved ArtifactFiles.
* @return A provider for a map of GAV coordinates to their resolved ArtifactFiles.
*/
static Map<String, ArtifactFiles> resolveArtifacts(Project project, Configuration runtimeConfiguration) {
// We create an ArtifactView to gather the component identifiers and library files.
// We specifically target external Maven dependencies (ModuleComponentIdentifiers).
def runtimeArtifactView = runtimeConfiguration.incoming.artifactView {
it.componentFilter { id -> id instanceof ModuleComponentIdentifier }
}

def artifactsMap = [:]

// 1. Gather library files directly from the view
runtimeArtifactView.artifacts.each { artifact ->
def id = artifact.id.componentIdentifier
if (id instanceof ModuleComponentIdentifier) {
String key = "${id.group}:${id.module}:${id.version}".toString()
artifactsMap[key] = new ArtifactFiles(null, artifact.file)
static Provider<Map<String, ArtifactFiles>> resolveArtifacts(Project project, Configuration runtimeConfiguration) {
return project.provider {
// We create an ArtifactView to gather the component identifiers and library files.
// We specifically target external Maven dependencies (ModuleComponentIdentifiers).
def runtimeArtifactView = runtimeConfiguration.incoming.artifactView {
it.componentFilter { id -> id instanceof ModuleComponentIdentifier }
}

def artifactsMap = [:]

// 1. Gather library files directly from the view
runtimeArtifactView.artifacts.each { artifact ->
def id = artifact.id.componentIdentifier
if (id instanceof ModuleComponentIdentifier) {
String key = "${id.group}:${id.module}:${id.version}".toString()
artifactsMap[key] = new ArtifactFiles(null, artifact.file)
}
}
}

// 2. Fetch corresponding POM files using ArtifactResolutionQuery
def componentIds = runtimeArtifactView.artifacts.collect { it.id.componentIdentifier }

if (!componentIds.isEmpty()) {
def result = project.dependencies.createArtifactResolutionQuery()
.forComponents(componentIds)
.withArtifacts(MavenModule, MavenPomArtifact)
.execute()
// 2. Fetch corresponding POM files using ArtifactResolutionQuery
def componentIds = runtimeArtifactView.artifacts.collect { it.id.componentIdentifier }
if (!componentIds.isEmpty()) {
def result = project.dependencies.createArtifactResolutionQuery()
.forComponents(componentIds)
.withArtifacts(MavenModule, MavenPomArtifact)
.execute()

result.resolvedComponents.each { component ->
component.getArtifacts(MavenPomArtifact).each { artifact ->
if (artifact instanceof ResolvedArtifactResult) {
def id = component.id
String key = "${id.group}:${id.module}:${id.version}".toString()

// Update the existing entry with the POM file
if (artifactsMap.containsKey(key)) {
artifactsMap[key].pomFile = artifact.file
} else {
artifactsMap[key] = new ArtifactFiles(artifact.file, null)
result.resolvedComponents.each { component ->
component.getArtifacts(MavenPomArtifact).each { artifact ->
if (artifact instanceof ResolvedArtifactResult) {
def id = component.id
String key = "${id.group}:${id.module}:${id.version}".toString()

// Update the existing entry with the POM file
if (artifactsMap.containsKey(key)) {
artifactsMap[key].pomFile = artifact.file
} else {
artifactsMap[key] = new ArtifactFiles(artifact.file, null)
}
}
}
}
}

return artifactsMap
}

return artifactsMap
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ import groovy.xml.XmlSlurper
import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Nested
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import org.slf4j.LoggerFactory

Expand All @@ -38,6 +42,7 @@ import java.util.zip.ZipFile
* mappings (POMs and Library artifacts) are provided as lazy input properties,
* making the task a pure function of its inputs.
*/
@CacheableTask
abstract class LicensesTask extends DefaultTask {
private static final String UTF_8 = "UTF-8"
private static final byte[] LINE_SEPARATOR = System
Expand Down Expand Up @@ -66,10 +71,11 @@ abstract class LicensesTask extends DefaultTask {
* A map of GAV coordinates (group:name:version) to their resolved POM and Library files.
* Populated by OssLicensesPlugin during configuration.
*/
@org.gradle.api.tasks.Input
@Nested
abstract org.gradle.api.provider.MapProperty<String, ArtifactFiles> getArtifactFiles()

@InputFile
@PathSensitive(PathSensitivity.NONE)
abstract RegularFileProperty getDependenciesJson()

@OutputDirectory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,10 @@ class OssLicensesPlugin implements Plugin<Project> {

// Task 1: Dependency Identification
// This task reads the AGP METADATA_LIBRARY_DEPENDENCIES_REPORT protobuf.
def dependenciesJson = baseDir.map { it.file("dependencies.json") }
TaskProvider<DependencyTask> dependencyTask = project.tasks.register(
"${variant.name}OssDependencyTask",
DependencyTask.class) {
it.dependenciesJson.set(dependenciesJson)
it.dependenciesJson.set(baseDir.map { it.file("dependencies.json") })
it.libraryDependenciesReport.set(variant.artifacts.get(SingleArtifact.METADATA_LIBRARY_DEPENDENCIES_REPORT.INSTANCE))
}
project.logger.debug("Registered task ${dependencyTask.name}")
Expand All @@ -73,28 +72,12 @@ class OssLicensesPlugin implements Plugin<Project> {
"${variant.name}OssLicensesTask",
LicensesTask.class) {
it.dependenciesJson.set(dependencyTask.flatMap { it.dependenciesJson })

it.artifactFiles.set(project.provider {
DependencyUtil.resolveArtifacts(project, variant.runtimeConfiguration)
})
it.artifactFiles.set(DependencyUtil.resolveArtifacts(project, variant.runtimeConfiguration))
}
project.logger.debug("Registered task ${licenseTask.name}")

// Register the LicensesTask output as a generated resource folder for AGP.
variant.sources.res.addGeneratedSourceDirectory(licenseTask, LicensesTask::getGeneratedDirectory)

// Task 3: Cleanup
// Ensures generated license files are deleted when running the clean task.
TaskProvider<LicensesCleanUpTask> cleanupTask = project.tasks.register(
"${variant.name}OssLicensesCleanUp",
LicensesCleanUpTask.class) {
it.generatedDirectory.set(baseDir)
}
project.logger.debug("Registered task ${cleanupTask.name}")

project.tasks.named("clean").configure {
it.dependsOn(cleanupTask)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public void testComplexDependencyGraphResolution() throws IOException {
runtimeClasspath.resolve();

// Execute resolution logic
Map<String, ArtifactFiles> artifactFiles = DependencyUtil.resolveArtifacts(appProject, runtimeClasspath);
Map<String, ArtifactFiles> artifactFiles = DependencyUtil.resolveArtifacts(appProject, runtimeClasspath).get();

// Assertions
// - Guava resolved to the higher version
Expand Down Expand Up @@ -121,7 +121,7 @@ public void testPomResolution() throws IOException {
Configuration runtimeClasspath = appProject.getConfigurations().getByName("runtimeClasspath");
runtimeClasspath.resolve();

Map<String, ArtifactFiles> artifactFiles = DependencyUtil.resolveArtifacts(appProject, runtimeClasspath);
Map<String, ArtifactFiles> artifactFiles = DependencyUtil.resolveArtifacts(appProject, runtimeClasspath).get();

assertThat(artifactFiles).containsKey("com.google.guava:guava:33.0.0-jre");
assertThat(artifactFiles.get("com.google.guava:guava:33.0.0-jre").getPomFile()).isNotNull();
Expand Down

This file was deleted.

Loading