Suppress missing license information for sub-projects in a multi-project build.
parent
b2bb05e6cc
commit
5d7e14d380
|
@ -15,9 +15,10 @@ object LicenseDependencyScanner {
|
|||
// scans and loads license data into the extension
|
||||
// - from jars on runtime/compile classpath
|
||||
|
||||
data class ScanDep(val project: Project, val preloadedText: MutableList<String>, val embeddedText: MutableList<String>, val missingText: MutableList<String>)
|
||||
|
||||
// THIS MUST BE IN "afterEvaluate" or run from a specific task.
|
||||
fun scanForLicenseData(project: Project, allProjects: Boolean,
|
||||
licenses: MutableList<LicenseData>): Triple<MutableList<String>, MutableList<String>, MutableList<String>> {
|
||||
fun scanForLicenseData(project: Project, allProjects: Boolean, licenses: MutableList<LicenseData>): ScanDep {
|
||||
|
||||
val preloadedText = mutableListOf<String>();
|
||||
val embeddedText = mutableListOf<String>();
|
||||
|
@ -25,7 +26,7 @@ object LicenseDependencyScanner {
|
|||
|
||||
|
||||
// NOTE: there will be some duplicates, so we want to remove them
|
||||
val dependencies = mutableSetOf<Dependency>()
|
||||
val dependencies = mutableSetOf<ProjAndDependency>()
|
||||
|
||||
if (allProjects) {
|
||||
project.allprojects.forEach { proj ->
|
||||
|
@ -39,36 +40,46 @@ object LicenseDependencyScanner {
|
|||
dependencies.addAll(scan(project, "runtimeClasspath"))
|
||||
}
|
||||
|
||||
// this will contain duplicates if sub-projects ALSO have the same deps
|
||||
val projectDependencies = dependencies.toList()
|
||||
|
||||
val missingLicenseInfo = mutableSetOf<Dependency>()
|
||||
val actuallyMissingLicenseInfo = mutableSetOf<Dependency>()
|
||||
val missingLicenseInfo = mutableSetOf<ProjAndDependency>()
|
||||
val actuallyMissingLicenseInfo = mutableSetOf<ProjAndDependency>()
|
||||
|
||||
val alreadyScanDeps = mutableSetOf<Dependency>()
|
||||
|
||||
if (licenses.isNotEmpty()) {
|
||||
// when we scan, we ONLY want to scan a SINGLE LAYER (if we have license info for module ID, then we don't need license info for it's children)
|
||||
val primaryLicense = licenses.first()
|
||||
|
||||
// scan to see if we have in our predefined section
|
||||
projectDependencies.forEach { info: Dependency ->
|
||||
projectDependencies.forEach { projAndDep: ProjAndDependency ->
|
||||
val dep = projAndDep.dep
|
||||
if (alreadyScanDeps.contains(dep)) {
|
||||
return@forEach
|
||||
}
|
||||
|
||||
val data: LicenseData? = try {
|
||||
AppLicensing.getLicense(info.mavenId())
|
||||
AppLicensing.getLicense(dep.mavenId())
|
||||
} catch (e: Exception) {
|
||||
println("\tError getting license information for ${info.mavenId()}")
|
||||
println("\tError getting license information for ${dep.mavenId()}")
|
||||
null
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
missingLicenseInfo.add(info)
|
||||
missingLicenseInfo.add(projAndDep)
|
||||
} else {
|
||||
if (!primaryLicense.extras.contains(data)) {
|
||||
preloadedText.add("\t\t${info.mavenId()} [${data.license}]")
|
||||
alreadyScanDeps.add(dep)
|
||||
|
||||
preloadedText.add("\t\t${dep.mavenId()} [${data.license}]")
|
||||
|
||||
// NOTE: the END copyright for these are determined by the DATE of the files!
|
||||
// Some dates are WRONG (because the jar build is mucked with), so we manually fix it
|
||||
if (data.copyright == 0) {
|
||||
// get the OLDEST date from the artifacts and use that as the copyright date
|
||||
var oldestDate = 0L
|
||||
info.artifacts.forEach { artifact ->
|
||||
dep.artifacts.forEach { artifact ->
|
||||
// get the date of the manifest file (which is the first entry)
|
||||
ZipInputStream(FileInputStream(artifact.file)).use {
|
||||
oldestDate = oldestDate.coerceAtLeast(it.nextEntry.lastModifiedTime.toMillis())
|
||||
|
@ -96,10 +107,15 @@ object LicenseDependencyScanner {
|
|||
|
||||
// now scan to see if the jar has a license blob in it
|
||||
if (missingLicenseInfo.isNotEmpty()) {
|
||||
missingLicenseInfo.forEach { info ->
|
||||
missingLicenseInfo.forEach { projAndDep: ProjAndDependency ->
|
||||
val dep = projAndDep.dep
|
||||
if (alreadyScanDeps.contains(dep)) {
|
||||
return@forEach
|
||||
}
|
||||
|
||||
// see if we have it in the dependency jar
|
||||
var licenseData: License? = null
|
||||
info.artifacts.forEach search@{ artifact ->
|
||||
dep.artifacts.forEach search@{ artifact ->
|
||||
val file = artifact.file
|
||||
try {
|
||||
if (file.canRead()) {
|
||||
|
@ -125,7 +141,7 @@ object LicenseDependencyScanner {
|
|||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println("\t$info [ERROR $file], ${e.message ?: e.javaClass}")
|
||||
println("\t$dep [ERROR $file], ${e.message ?: e.javaClass}")
|
||||
}
|
||||
|
||||
return@search
|
||||
|
@ -134,27 +150,48 @@ object LicenseDependencyScanner {
|
|||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println("\t$info [ERROR $file], ${e.message ?: e.javaClass}")
|
||||
println("\t$dep [ERROR $file], ${e.message ?: e.javaClass}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (licenseData != null) {
|
||||
embeddedText.add("\t\t$info [$licenseData]")
|
||||
alreadyScanDeps.add(dep)
|
||||
embeddedText.add("\t\t$dep [$licenseData]")
|
||||
} else {
|
||||
actuallyMissingLicenseInfo.add(info)
|
||||
actuallyMissingLicenseInfo.add(projAndDep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (actuallyMissingLicenseInfo.isNotEmpty()) {
|
||||
actuallyMissingLicenseInfo.forEach { missingDep ->
|
||||
missingText.add("\t ${missingDep.mavenId()}")
|
||||
// we have to prune sub-project data first...
|
||||
val projectMavenIds = mutableSetOf<String>()
|
||||
project.allprojects.forEach {
|
||||
projectMavenIds.add("${it.group}:${it.name}:${it.version}")
|
||||
}
|
||||
|
||||
actuallyMissingLicenseInfo.forEach { missingDepAndProj ->
|
||||
// we DO NOT want to show missing deps for project sub-projects.
|
||||
val proj = missingDepAndProj.project
|
||||
val dep = missingDepAndProj.dep
|
||||
|
||||
if (alreadyScanDeps.contains(dep)) {
|
||||
return@forEach
|
||||
}
|
||||
alreadyScanDeps.add(dep)
|
||||
|
||||
val mavenId = dep.mavenId()
|
||||
|
||||
// if the missing dep IS ALSO the same as a subproject .... we don't want to report it
|
||||
if (!projectMavenIds.contains(mavenId)) {
|
||||
missingText.add("\t ${dep.mavenId()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Triple(preloadedText, embeddedText, missingText)
|
||||
return ScanDep(project, preloadedText, embeddedText, missingText)
|
||||
}
|
||||
|
||||
|
||||
|
@ -167,9 +204,9 @@ object LicenseDependencyScanner {
|
|||
*
|
||||
* This is an actual problem...
|
||||
*/
|
||||
private fun scan(project: Project, configurationName: String): List<Dependency> {
|
||||
private fun scan(project: Project, configurationName: String): List<ProjAndDependency> {
|
||||
|
||||
val projectDependencies = mutableListOf<Dependency>()
|
||||
val projectDependencies = mutableListOf<ProjAndDependency>()
|
||||
val config = project.configurations.getByName(configurationName)
|
||||
if (!config.isCanBeResolved) {
|
||||
return projectDependencies
|
||||
|
@ -204,16 +241,19 @@ object LicenseDependencyScanner {
|
|||
} catch (e: Exception) {
|
||||
listOf()
|
||||
}
|
||||
projectDependencies.add(Dependency(group, name, version, artifacts))
|
||||
projectDependencies.add(ProjAndDependency(project, Dependency(group, name, version, artifacts)))
|
||||
}
|
||||
|
||||
return projectDependencies
|
||||
}
|
||||
|
||||
internal data class Dependency(val group: String,
|
||||
val name: String,
|
||||
val version: String,
|
||||
val artifacts: List<Artifact>) {
|
||||
internal data class ProjAndDependency(val project: Project, val dep: Dependency)
|
||||
|
||||
internal data class Dependency(
|
||||
val group: String,
|
||||
val name: String,
|
||||
val version: String,
|
||||
val artifacts: List<Artifact>) {
|
||||
|
||||
fun mavenId(): String {
|
||||
return "$group:$name:$version"
|
||||
|
|
|
@ -36,7 +36,7 @@ internal open class LicenseInjector @Inject constructor(@Internal val extension:
|
|||
// This MUST be first, since it loads license data that is used elsewhere
|
||||
// show scanning or missing, but not both
|
||||
// NOTE: we scan the dependencies in ALL subprojects as well.
|
||||
val (preloadedText, embeddedText, missingText) = extension.scanDependencies(project, true)
|
||||
val (proj, preloadedText, embeddedText, missingText) = extension.scanDependencies(project, true)
|
||||
|
||||
// validate the license text configuration section in the gradle file ONLY WHEN PUSHING A JAR
|
||||
val licensing = extension.licenses
|
||||
|
|
|
@ -53,7 +53,3 @@ class LicensePlugin : Plugin<Project> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -181,14 +181,16 @@ open class Licensing(private val project: Project) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// scan as part of the plugin
|
||||
fun scanDependencies(project: Project, allProjects: Boolean): Triple<MutableList<String>, MutableList<String>, MutableList<String>> {
|
||||
fun scanDependencies(project: Project, allProjects: Boolean): LicenseDependencyScanner.ScanDep {
|
||||
// now we want to add license information that we know about from our dependencies to our list
|
||||
// just to make it clear, license information CAN CHANGE BETWEEN VERSIONS! For example, JNA changed from GPL to Apache in version 4+
|
||||
// we associate the artifact group + id + (start) version as a license.
|
||||
// if a license for a dependency is UNKNOWN, then we emit a warning to the user to add it as a pull request
|
||||
// if a license version is not specified, then we use the default
|
||||
val textOutput = LicenseDependencyScanner.scanForLicenseData(project, allProjects, this.licenses)
|
||||
val depInfo = LicenseDependencyScanner.scanForLicenseData(project, allProjects, this.licenses)
|
||||
|
||||
|
||||
// we only should include the kotlin license information IF we actually use kotlin.
|
||||
|
@ -211,7 +213,7 @@ open class Licensing(private val project: Project) {
|
|||
}
|
||||
}
|
||||
|
||||
return textOutput
|
||||
return depInfo
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue