stevedlawrence commented on code in PR #919:
URL: https://github.com/apache/daffodil/pull/919#discussion_r1092075599


##########
project/OsgiCheck.scala:
##########
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more

Review Comment:
   I know sbt can be miserable, especially when adding new tasks. I thought I'd 
test some of my ideas for making this more sbt-y and make sure they actually 
worked. It actually wasn't too difficult to implement (granted, I've a bunch of 
sbt plugin development) and I accidentally implemented the whole thing. The 
most complex logic is detecting packages owned by multiple projects in  
functional way. It looks a bit messy, but I don't think it's terrible. Aside 
from that, most of this is sbt plugin boilerplate.
   
   Some benefits to this approach:
   * Like before, running `sbt osgiCheck` will check and output all packages 
owned by multiple subprojects
   * You can see all packages owned by a single subproject with the 
osgiOwnedPackages task, e.g. `sbt daffodil-lib/osgiOwnedPackages` shows just 
the packages owned by daffodil-lib
   * Ignoring a subproject from this check is as easy as disabling the plugin 
for the subproject, e.g. `.disablePlugins(OsgiCheckPlugin)`
   
   Implementation below:
   
   ```scala
   import sbt._
   import sbt.Keys._
   import sbt.KeyRanks._
   
   object OsgiCheckPlugin extends AutoPlugin {
   
     class OsgiCheckException()
       extends RuntimeException("OSGI check failed")
       with FeedbackProvidedException
   
     object autoImport {
       val osgiOwnedPackages = taskKey[Set[String]]("Get all packages owned by 
this project").withRank(BTask)
       val osgiOwnedPackagesWithOwner = taskKey[(Set[String], String)]("Get a 
tuple of the osgiOwnedPackages and the project name that owns 
them").withRank(Invisible)
       val osgiCheck = taskKey[Unit]("Check all subpackages for osgi 
conflicts").withRank(ATask)
     }
   
     import autoImport._
   
     private val packageMatcher = """^\s*package (\S+);?.*$""".r
   
     override def trigger = allRequirements
   
     val allSubprojectsFilter = ScopeFilter(inAggregates(ThisProject, 
includeRoot=false))
     
     override def projectSettings: Seq[Def.Setting[_]] = {Seq(
       osgiOwnedPackages := {
         (Compile / sources).value.flatMap { file =>
           var source = scala.io.Source.fromFile(file)
           val optPackage = source.getLines.collectFirst {
             case packageMatcher(packageName) => packageName
           }
           optPackage
         }.toSet
       },
       osgiOwnedPackagesWithOwner := {
         (osgiOwnedPackages.value, name.value)
       },
       osgiCheck := {
         val logger = streams.value.log
         
         // create a List of tuples of all osgiOwnedPackages and their owner 
from all
         // subprojects. If a subproject disables this plugin, then it 
contributes tuple
         // of empty set and empty string and will be ignored
         val subprojectPackagesAndOwner = (osgiOwnedPackagesWithOwner ?? 
(Set.empty -> ""))
           .all(allSubprojectsFilter).value
         
         // flatten all of our tuples so we have a single list of package name 
->
         // project owner tuples. At this point, there might be multiple owners
         // for the same package name in this list
         val packageOwnerTuples = subprojectPackagesAndOwner.flatMap { case 
(ownedPackages, packageOwner) =>
           ownedPackages.map { _ -> packageOwner }
         }
         
         // create a map, grouping with a key of package name and value of all 
of the
         // owners that claim to own it. If only one project owns a package, 
the value
         // should be a list of one.
         val packageOwnersMap = packageOwnerTuples
           .groupBy { case (packageName, _) => packageName }
           .mapValues { list => list.map { case (_, packageOwner) => 
packageOwner } }
         
         // find any packages with multiple project owners and error
         val multipleOwners = packageOwnersMap.filter { case (_, owners) => 
owners.length > 1 }
         if (multipleOwners.size > 0) {
           logger.err("Packages found owned by multiple projects, violating 
OSGI:")
           multipleOwners.foreach { case (packageName, owners) =>
             logger.err(s"- package $packageName: ${owners.mkString(", ")}")
           }
           throw new OsgiCheckException()
         }
       }
     )}
   
     override val globalSettings: Seq[Setting[_]] = {Seq(
       // the osgiCheck does aggregation itself by inspecting all subproject, 
it does
       // not need to be aggregated
       osgiCheck / aggregate := false
     )}
   
   }
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to