Skip to content

Commit

Permalink
Add android library subproject dependencies to the report
Browse files Browse the repository at this point in the history
  • Loading branch information
mkubiczek committed Dec 30, 2020
1 parent 0a254df commit bdb53bf
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 28 deletions.
62 changes: 34 additions & 28 deletions src/main/kotlin/com/jaredsburrows/license/LicenseReportTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import java.util.UUID
import org.gradle.api.DefaultTask
import org.gradle.api.Task
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ResolvedArtifact
import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.logging.LogLevel
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
Expand Down Expand Up @@ -96,38 +98,16 @@ open class LicenseReportTask : DefaultTask() { // tasks can't be final

// If Android project, add extra configurations
variantName?.let { variant ->
// Add buildType configurations
configurations.find { it.name == "compile" }?.let {
configurationSet.add(configurations.getByName("${buildType}Compile"))
}
configurations.find { it.name == "api" }?.let {
configurationSet.add(configurations.getByName("${buildType}Api"))
}
configurations.find { it.name == "implementation" }?.let {
configurationSet.add(configurations.getByName("${buildType}Implementation"))
}

// Add productFlavors configurations
productFlavors.forEach { flavor ->
// Works for productFlavors and productFlavors with dimensions
if (variant.capitalize().contains(flavor.name.capitalize())) {
configurations.find { it.name == "compile" }?.let {
configurationSet.add(configurations.getByName("${flavor.name}Compile"))
}
configurations.find { it.name == "api" }?.let {
configurationSet.add(configurations.getByName("${flavor.name}Api"))
}
configurations.find { it.name == "implementation" }?.let {
configurationSet.add(configurations.getByName("${flavor.name}Implementation"))
}
}
configurations.find { it.name == "${variant}RuntimeClasspath" }?.also {
configurationSet.add(it)
}
}

// Iterate through all the configurations's dependencies
configurationSet.forEach { set ->
if (set.isCanBeResolved) {
set.resolvedConfiguration.lenientConfiguration.artifacts.forEach { artifact ->
configurationSet.forEach { configuration ->
if (configuration.isCanBeResolved) {
val allDeps = configuration.resolvedConfiguration.lenientConfiguration.allModuleDependencies
getResolvedArtifactsFromResolvedDependencies(allDeps).forEach { artifact ->
val id = artifact.moduleVersion.id
val gav = "${id.group}:${id.name}:${id.version}@pom"
configurations.getByName(pomConfiguration).dependencies.add(
Expand All @@ -138,6 +118,32 @@ open class LicenseReportTask : DefaultTask() { // tasks can't be final
}
}

private fun getResolvedArtifactsFromResolvedDependencies(
resolvedDependencies: Set<ResolvedDependency>
): Set<ResolvedArtifact> {
val resolvedArtifacts = hashSetOf<ResolvedArtifact>()
for (resolvedDependency in resolvedDependencies) {
try {
if (resolvedDependency.moduleVersion == "unspecified") {
/**
* Attempting to getAllModuleArtifacts on a local library project will result
* in AmbiguousVariantSelectionException as there are not enough criteria
* to match a specific variant of the library project. Instead we skip the
* the library project itself and enumerate its dependencies.
*/
resolvedArtifacts.addAll(
getResolvedArtifactsFromResolvedDependencies(resolvedDependency.children)
)
} else {
resolvedArtifacts.addAll(resolvedDependency.allModuleArtifacts)
}
} catch (e: Exception) {
logger.warn("Failed to process $resolvedDependency.name", e)
}
}
return resolvedArtifacts
}

/** Get POM information from the dependency artifacts. */
private fun generatePOMInfo() {
// Iterate through all POMs in order from our custom POM configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,144 @@ final class LicensePluginAndroidSpec extends Specification {
taskName << ['licenseDebugReport', 'licenseReleaseReport']
}

@Unroll def '#taskName with default buildTypes, multi module and android and android'() {
given:
testProjectDir.newFile('settings.gradle') <<
"""
include 'subproject'
"""

buildFile <<
"""
buildscript {
dependencies {
classpath files($classpathString)
}
}
allprojects {
repositories {
maven {
url '${mavenRepoUrl}'
}
}
}
apply plugin: 'com.android.application'
apply plugin: 'com.jaredsburrows.license'
android {
compileSdkVersion 28
defaultConfig {
applicationId 'com.example'
}
}
dependencies {
api project(':subproject')
implementation 'group:name:1.0.0'
}
project(':subproject') {
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
}
dependencies {
implementation 'com.android.support:design:26.1.0'
}
}
"""

when:
def result = gradleWithCommand(testProjectDir.root, "${taskName}", '-s')
def actualHtml = new File("${reportFolder}/${taskName}.html").text
def expectedHtml =
"""
<html>
<head>
<style>body { font-family: sans-serif } pre { background-color: #eeeeee; padding: 1em; white-space: pre-wrap; display: inline-block }</style>
<title>Open source licenses</title>
</head>
<body>
<h3>Notice for packages:</h3>
<ul>
<li><a href="#1934118923">design (26.1.0)</a>
<dl>
<dt>Copyright &copy; 20xx The original author or authors</dt>
</dl>
</li>
<a name="1934118923"></a>
<pre>${myGetLicenseText('apache-2.0.txt')}</pre>
<br>
<hr>
<li><a href="#-296292112">Fake dependency name (1.0.0)</a>
<dl>
<dt>Copyright &copy; 2017 name</dt>
</dl>
</li>
<a name="-296292112"></a>
<pre>Some license
<a href="http://website.tld/">http://website.tld/</a></pre>
<br>
<hr>
</ul>
</body>
</html>
"""
def actualJson = new File("${reportFolder}/${taskName}.json").text
def expectedJson =
"""
[
{
"project":"design",
"description":null,
"version":"26.1.0",
"developers":[],
"url":null,
"year":null,
"licenses":[
{
"license":"The Apache Software License",
"license_url":"http://www.apache.org/licenses/LICENSE-2.0.txt"
}
],
"dependency":"com.android.support:design:26.1.0"
},
{
"project":"Fake dependency name",
"description":"Fake dependency description",
"version":"1.0.0",
"developers":[
"name"
],
"url":"https://github.com/user/repo",
"year":"2017",
"licenses":[
{
"license":"Some license",
"license_url":"http://website.tld/"
}
],
"dependency":"group:name:1.0.0"
}
]
"""

then:
result.task(":${taskName}").outcome == SUCCESS
result.output.find("Wrote HTML report to .*${reportFolder}/${taskName}.html.")
result.output.find("Wrote JSON report to .*${reportFolder}/${taskName}.json.")
assertHtml(expectedHtml, actualHtml)
assertJson(expectedJson, actualJson)

where:
taskName << ['licenseDebugReport', 'licenseReleaseReport']
}

@Unroll def '#taskName with reports enabled and copy enabled #copyEnabled'() {
given:
buildFile <<
Expand Down

0 comments on commit bdb53bf

Please sign in to comment.