New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explanation [ not issue ] #169

Open
leobenkel opened this Issue Nov 14, 2018 · 2 comments

Comments

Projects
None yet
2 participants
@leobenkel
Copy link

leobenkel commented Nov 14, 2018

Hello,
Can anyone explain to me what

moduleGraphSbt :=
        ignoreMissingUpdate.value
          .configuration(configuration.value)
          .map(report ⇒ SbtUpdateReport.fromConfigurationReport(report, crossProjectId.value))
          .getOrElse(ModuleGraph.empty),

is doing ? Here:

moduleGraphSbt :=
ignoreMissingUpdate.value.configuration(configuration.value).map(report SbtUpdateReport.fromConfigurationReport(report, crossProjectId.value)).getOrElse(ModuleGraph.empty),

I am trying to build my own sbt plugin to analyze dependencies and I am trying to reproduce the same graph of dependencies that you have. But I struggle with this step.

@jrudolph

This comment has been minimized.

Copy link
Owner

jrudolph commented Nov 17, 2018

Here are the steps:

  • ignoreMissingUpdate is very similar to the regular update step, it runs the ivy resolution and returns an UpdateReport
  • configuration(...) returns the result of the resolution for one ivy configuration (like compile, provided, runtime, or test) if it exists
  • SbtUpdateReport.fromConfigurationReport does the real work of converting the sbt ConfigurationReport into a ModuleGraph which is the sbt-dependency-graph data structure to represent the dependencies

See

def fromConfigurationReport(report: ConfigurationReport, rootInfo: sbt.ModuleID): ModuleGraph = {
implicit def id(sbtId: sbt.ModuleID): ModuleId = ModuleId(sbtId.organization, sbtId.name, sbtId.revision)
def moduleEdges(orgArt: OrganizationArtifactReport): Seq[(Module, Seq[Edge])] = {
val chosenVersion = orgArt.modules.find(!_.evicted).map(_.module.revision)
orgArt.modules.map(moduleEdge(chosenVersion))
}
def moduleEdge(chosenVersion: Option[String])(report: ModuleReport): (Module, Seq[Edge]) = {
val evictedByVersion = if (report.evicted) chosenVersion else None
val jarFile = report.artifacts.find(_._1.`type` == "jar").orElse(report.artifacts.find(_._1.extension == "jar")).map(_._2)
(
Module(
id = report.module,
license = report.licenses.headOption.map(_._1),
evictedByVersion = evictedByVersion,
jarFile = jarFile,
error = report.problem),
report.callers.map(caller Edge(caller.caller, report.module)))
}
val (nodes, edges) = report.details.flatMap(moduleEdges).unzip
val root = Module(rootInfo)
ModuleGraph(root +: nodes, edges.flatten)
}

I'd recommend to use an IDEA like IntelliJ IDEA and use "jump to definition" (ctrl-click) to discover what code like this is doing.

@leobenkel

This comment has been minimized.

Copy link
Author

leobenkel commented Nov 18, 2018

Thats what I was doing but didn't really know how SBT was working. Thank you so much for the explanation !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment