Skip to content

Commit

Permalink
Handle replacements
Browse files Browse the repository at this point in the history
  • Loading branch information
ianoc committed Jun 16, 2022
1 parent a25f9b1 commit dd012d7
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 135 deletions.
1 change: 0 additions & 1 deletion src/scala/com/github/johnynek/bazel_deps/Commands.scala
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ object Command {
"relative path to the file to emit target info into (usually called resolvedOutput.json)."
)


(repoRoot |@| depsFile |@| resolvedOutput |@| Verbosity.opt)
.map(Generate(_, _, _, _))
}
Expand Down
1 change: 0 additions & 1 deletion src/scala/com/github/johnynek/bazel_deps/DepsModel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1844,7 +1844,6 @@ case class Options(
def getTransitivity: Transitivity =
transitivity.getOrElse(Transitivity.Exports)


def getResolverCache: ResolverCache =
resolverCache.getOrElse(ResolverCache.Local)

Expand Down
15 changes: 8 additions & 7 deletions src/scala/com/github/johnynek/bazel_deps/MakeDeps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@ object MakeDeps {
System.exit(1)
case Success((normalized, shas, duplicates)) =>
// build the BUILDs in thirdParty
val artifacts = Writer.artifactEntries(normalized, duplicates, shas, model) match {
case Right(t) => t
case Left(errs) =>
errs.toList.foreach { e => logger.error(e.message) }
System.exit(-1)
sys.error("exited already")
}
val artifacts =
Writer.artifactEntries(normalized, duplicates, shas, model) match {
case Right(t) => t
case Left(errs) =>
errs.toList.foreach { e => logger.error(e.message) }
System.exit(-1)
sys.error("exited already")
}

executeGenerate(
model,
Expand Down
249 changes: 123 additions & 126 deletions src/scala/com/github/johnynek/bazel_deps/Writer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,152 +63,149 @@ object Writer {

private[this] val logger = LoggerFactory.getLogger("Writer")



case class DataSource(
sha1: Option[String],
sha256: Option[String],
repository: Option[String],
urls: List[String]
)

case class ArtifactEntry(
artifact: String,
version: String,
lang: String,
binaryJar: Option[DataSource],
sourceJar: Option[DataSource],
resolutionComment: Option[String],
deps: List[String],
exports: List[String] // "com/amazonaws:jmespath_java"
)

private def concreteToArtifactEntry(coord: MavenCoordinate,
g: Graph[MavenCoordinate, Unit],
duplicates: Map[UnversionedCoordinate, Set[Edge[MavenCoordinate, Unit]]],
shas: Map[MavenCoordinate, ResolvedShasValue],
model: Model
): ArtifactEntry = {
val servers = model.getOptions.getResolvers.map(s => (s.id, s.url)).toMap
val lang = language(g, model)
val prefix = model.getOptions.getNamePrefix

val isRoot = model.dependencies.roots(coord)

val binaryJar = shas.get(coord).map { sha =>
DataSource(
sha1 = sha.binaryJar.sha1.map(_.toHex),
sha256 = sha.binaryJar.sha256.map(_.toHex),
repository = servers.get(sha.binaryJar.serverId),
urls = List(sha.binaryJar.url.toList).flatten
)
}

val sourceJar = shas.get(coord).flatMap(_.sourceJar).map { sourceJar =>
DataSource(
sha1 = sourceJar.sha1.map(_.toHex),
sha256 = sourceJar.sha256.map(_.toHex),
repository = servers.get(sourceJar.serverId),
urls = List(sourceJar.url.toList).flatten
)
}
def replaced(m: MavenCoordinate): Boolean =
model.getReplacements.get(m.unversioned).isDefined


val resolutionComment = duplicates.get(coord.unversioned).map { vs =>
val status =
if (isRoot) s"fixed to ${coord.version.asString}"
else if (vs.map(_.destination.version).max == coord.version)
s"promoted to ${coord.version.asString}"
else s"downgraded to ${coord.version.asString}"

s"""# duplicates in ${coord.unversioned.asString} $status\n""" +
vs.filterNot(e => replaced(e.source))
.map { e =>
s"""# - ${e.source.asString} wanted version ${e.destination.version.asString}\n"""
}
.toSeq
.sorted
.mkString("")
}


val deps = g.hasSource(coord).toList

val manualExports = model.dependencies
.exportedUnversioned(coord.unversioned, model.getReplacements)
.right
.get
sha1: Option[String],
sha256: Option[String],
repository: Option[String],
urls: List[String]
)

val l = lang(coord.unversioned).asString
ArtifactEntry(
artifact = coord.unversioned.asString,
version = coord.version.asString,
lang = l,
binaryJar = binaryJar,
sourceJar = sourceJar,
resolutionComment = resolutionComment,
deps = deps.map(_.destination.unversioned.asString),
exports = manualExports.map(_.asString)
case class ArtifactReplacement(
lang: String,
bazelTarget: String
)
}

private def replacedToArtifactEntry(uc: UnversionedCoordinate,
replacedEntry: ReplacementRecord,
g: Graph[MavenCoordinate, Unit],
duplicates: Map[UnversionedCoordinate, Set[Edge[MavenCoordinate, Unit]]],
shas: Map[MavenCoordinate, ResolvedShasValue],
model: Model
): ArtifactEntry = ???
case class ArtifactEntry(
artifact: String,
version: String,
lang: String,
binaryJar: Option[DataSource],
sourceJar: Option[DataSource],
resolutionComment: Option[String],
deps: List[String],
exports: List[String], // "com/amazonaws:jmespath_java"
replacementData: Option[ArtifactReplacement] = None
)

def artifactEntries(
private def concreteToArtifactEntry(
coord: MavenCoordinate,
g: Graph[MavenCoordinate, Unit],
duplicates: Map[UnversionedCoordinate, Set[Edge[MavenCoordinate, Unit]]],
shas: Map[MavenCoordinate, ResolvedShasValue],
model: Model
): Either[NonEmptyList[TargetsError], List[ArtifactEntry]] = {
/** Check that all the exports are well-defined TODO make sure to write
* targets for replaced nodes
*/
val badExports =
g.nodes.toList.flatMap { c =>
val uv = c.unversioned
model.dependencies.exportedUnversioned(
uv,
model.getReplacements
) match {
case Left(baddies) =>
List(TargetsError.BadExport(c.unversioned, baddies))
case Right(_) => Nil
}
): ArtifactEntry = {
val servers = model.getOptions.getResolvers.map(s => (s.id, s.url)).toMap
val lang = language(g, model)
val prefix = model.getOptions.getNamePrefix

val isRoot = model.dependencies.roots(coord)

val binaryJar = shas.get(coord).map { sha =>
DataSource(
sha1 = sha.binaryJar.sha1.map(_.toHex),
sha256 = sha.binaryJar.sha256.map(_.toHex),
repository = servers.get(sha.binaryJar.serverId),
urls = List(sha.binaryJar.url.toList).flatten
)
}

val check = badExports match {
case h :: tail => Left(NonEmptyList(h, tail))
case Nil => Right(())
}
check.map { _ =>
val sourceJar = shas.get(coord).flatMap(_.sourceJar).map { sourceJar =>
DataSource(
sha1 = sourceJar.sha1.map(_.toHex),
sha256 = sourceJar.sha256.map(_.toHex),
repository = servers.get(sourceJar.serverId),
urls = List(sourceJar.url.toList).flatten
)
}
def replaced(m: MavenCoordinate): Boolean =
model.getReplacements.get(m.unversioned).isDefined

val resolutionComment = duplicates.get(coord.unversioned).map { vs =>
val status =
if (isRoot) s"fixed to ${coord.version.asString}"
else if (vs.map(_.destination.version).max == coord.version)
s"promoted to ${coord.version.asString}"
else s"downgraded to ${coord.version.asString}"

s"""# duplicates in ${coord.unversioned.asString} $status\n""" +
vs.filterNot(e => replaced(e.source))
.map { e =>
s"""# - ${e.source.asString} wanted version ${e.destination.version.asString}\n"""
}
.toSeq
.sorted
.mkString("")
}

val deps = g.hasSource(coord).toList

val manualExports = model.dependencies
.exportedUnversioned(coord.unversioned, model.getReplacements)
.right
.get

val l = lang(coord.unversioned).asString
ArtifactEntry(
artifact = coord.unversioned.asString,
version = coord.version.asString,
lang = l,
binaryJar = binaryJar,
sourceJar = sourceJar,
resolutionComment = resolutionComment,
deps = deps.map(_.destination.unversioned.asString),
exports = manualExports.map(_.asString)
)
}

def artifactEntries(
g: Graph[MavenCoordinate, Unit],
duplicates: Map[UnversionedCoordinate, Set[Edge[MavenCoordinate, Unit]]],
shas: Map[MavenCoordinate, ResolvedShasValue],
model: Model
): Either[NonEmptyList[TargetsError], List[ArtifactEntry]] = {

/** Here are all the explicit artifacts
*/
/** Check that all the exports are well-defined TODO make sure to write
* targets for replaced nodes
*/
val badExports =
g.nodes.toList.flatMap { c =>
val uv = c.unversioned
model.dependencies.exportedUnversioned(
uv,
model.getReplacements
) match {
case Left(baddies) =>
List(TargetsError.BadExport(c.unversioned, baddies))
case Right(_) => Nil
}
}

val explicitEntries: List[ArtifactEntry] = g.nodes.filterNot(replaced).toIterator.map { m =>
concreteToArtifactEntry(m, g, duplicates, shas, model)
}.toList
val check = badExports match {
case h :: tail => Left(NonEmptyList(h, tail))
case Nil => Right(())
}
check.map { _ =>
def replaced(m: MavenCoordinate): Boolean =
model.getReplacements.get(m.unversioned).isDefined

/** Here are any that are replaced, they may not appear above:
*/
val replacedEntries: List[ArtifactEntry] = model.getReplacements.unversionedToReplacementRecord.toIterator.map { case (uv, rr) =>
replacedToArtifactEntry(uv, rr, g, duplicates, shas, model)
/** Here are all the explicit artifacts
*/

g.nodes.toIterator.map { m =>
val concrete = concreteToArtifactEntry(m, g, duplicates, shas, model)
model.getReplacements.get(m.unversioned) match {
case Some(replacement) =>
concrete.copy(
replacementData = Some(
ArtifactReplacement(
lang = replacement.lang.asReversableString,
bazelTarget = replacement.target.asString
)
)
)
case None => concrete
}
}.toList

explicitEntries ++ replacedEntries
}
}

Expand Down

0 comments on commit dd012d7

Please sign in to comment.