From ed2cae987c5bc391ef229677800d333a0de598c6 Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Wed, 3 Jul 2024 09:30:45 +0200 Subject: [PATCH] Resolve license inheritence in update report In addition to the unit test, tested by running the scripted tests on the `use-update` branch of `sbt-license-report` at https://github.com/sbt/sbt-license-report/pull/123 --- .../lmcoursier/internal/SbtUpdateReport.scala | 28 +++++++++++++++++-- .../scala/lmcoursier/ResolutionSpec.scala | 13 +++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/internal/SbtUpdateReport.scala b/modules/lm-coursier/src/main/scala/lmcoursier/internal/SbtUpdateReport.scala index 55bf9fc4a..e41d6915d 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/internal/SbtUpdateReport.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/internal/SbtUpdateReport.scala @@ -4,15 +4,16 @@ import java.io.File import java.net.URL import java.util.GregorianCalendar import java.util.concurrent.ConcurrentHashMap - import coursier.cache.CacheUrl import coursier.{Attributes, Dependency, Module, Project, Resolution} -import coursier.core.{Classifier, Configuration, Extension, Publication, Type} +import coursier.core.{Classifier, Configuration, Extension, Info, Publication, Type} import coursier.maven.MavenAttributes import coursier.util.Artifact import sbt.librarymanagement.{Artifact => _, Configuration => _, _} import sbt.util.Logger +import scala.annotation.tailrec + private[internal] object SbtUpdateReport { private def caching[K, V](f: K => V): K => V = { @@ -226,6 +227,26 @@ private[internal] object SbtUpdateReport { ) } + /** + * Assemble the project info, resolving inherited fields. Only implements resolving + * the fields that are relevant for moduleReport + * + * @see https://maven.apache.org/pom.html#Inheritance + * @see https://maven.apache.org/ref/3-LATEST/maven-model-builder/index.html#Inheritance_Assembly + */ + def assemble(project: Project): Project = { + @tailrec + def licenseInfo(project: Project): Seq[Info.License] = { + if (project.info.licenseInfo.nonEmpty || project.parent.isEmpty) + project.info.licenseInfo + else + licenseInfo(lookupProject(project.parent.get).get) + } + project.withInfo( + project.info.withLicenseInfo(licenseInfo(project)) + ) + } + val m = Dependency(thisModule._1, "") val directReverseDependencies = res.rootDependencies.toSet.map(clean).map(_.withVersion("")) .map( @@ -252,6 +273,7 @@ private[internal] object SbtUpdateReport { groupedDepArtifacts.toVector.map { case (dep, artifacts) => val proj = lookupProject(dep.moduleVersion).get + val assembledProject = assemble(proj) // FIXME Likely flaky... val dependees = reverseDependencies @@ -280,7 +302,7 @@ private[internal] object SbtUpdateReport { moduleReport(( dep, dependees, - proj, + assembledProject, filesOpt, classLoaders, )) diff --git a/modules/lm-coursier/src/test/scala/lmcoursier/ResolutionSpec.scala b/modules/lm-coursier/src/test/scala/lmcoursier/ResolutionSpec.scala index b74a84d2f..310fd014b 100644 --- a/modules/lm-coursier/src/test/scala/lmcoursier/ResolutionSpec.scala +++ b/modules/lm-coursier/src/test/scala/lmcoursier/ResolutionSpec.scala @@ -235,4 +235,17 @@ final class ResolutionSpec extends AnyPropSpec with Matchers { resolution should be('right) } + + property("resolve licenses from parent poms") { + val dependencies = + Vector(("org.apache.commons" % "commons-compress" % "1.26.2")) + val coursierModule = module(lmEngine, stubModule, dependencies, Some("2.12.4")) + val resolution = + lmEngine.update(coursierModule, UpdateConfiguration(), UnresolvedWarningConfiguration(), log) + + resolution should be('right) + val componentConfig = resolution.right.get.configurations.find(_.configuration == Compile.toConfigRef).get + val compress = componentConfig.modules.find(_.module.name == "commons-compress").get + compress.licenses should have size 1 + } }