Skip to content

Commit

Permalink
Use coursier to fetch versions (#305)
Browse files Browse the repository at this point in the history
  • Loading branch information
d10xa authored Jan 7, 2021
1 parent 0a3ecdc commit 41d00bb
Show file tree
Hide file tree
Showing 65 changed files with 496 additions and 1,133 deletions.
7 changes: 3 additions & 4 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 0 additions & 15 deletions .idea/runConfigurations/debug5005.xml

This file was deleted.

2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ sbt -jvm-debug 5005

In intellij idea:

Edit Configurations... -> Add New Configuration -> Remote JVM Debug

run task `debug5005`

Execute sbt task `run` manually.
Expand Down
1 change: 0 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ addCompilerPlugin(
)

libraryDependencies ++= Seq(
"org.scala-lang.modules" %% "scala-xml" % "1.3.0",
"com.github.scopt" %% "scopt" % "3.7.1",
"ch.qos.logback" % "logback-classic" % "1.2.3",
"com.typesafe.scala-logging" %% "scala-logging" % "3.9.2",
Expand Down
10 changes: 2 additions & 8 deletions src/main/scala/ru/d10xa/jadd/cli/Config.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package ru.d10xa.jadd.cli

import coursier.Resolve
import ru.d10xa.jadd.cli.Command.Repl
import ru.d10xa.jadd.core.types.ScalaVersion
import ru.d10xa.jadd.repository.RepositoryConstants
import ru.d10xa.jadd.show.JaddFormatShowPrinter
import ru.d10xa.jadd.show.ShowPrinter

Expand All @@ -13,13 +13,7 @@ final case class Config(
requirements: Seq[String] = Seq.empty,
projectDir: String = System.getProperty("user.dir"),
shortcutsUri: String = "classpath:jadd-shortcuts.csv",
repositories: Seq[String] = Seq(
RepositoryConstants.mavenCentral,
RepositoryConstants.jcenter,
// TODO get repository path from ~/.m2/settings.xml or use default
// TODO support for ~
s"${System.getProperty("user.home")}/.m2/repository"
),
repositories: Seq[String] = Resolve.defaultRepositories.map(_.repr),
showPrinter: ShowPrinter = JaddFormatShowPrinter.withVersions,
scalaVersion: Option[ScalaVersion] = None,
proxy: Option[String] = None,
Expand Down
30 changes: 0 additions & 30 deletions src/main/scala/ru/d10xa/jadd/core/Artifact.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ import com.typesafe.scalalogging.StrictLogging
import coursier.core.Version
import ru.d10xa.jadd.core.types.GroupId
import ru.d10xa.jadd.core.types.ScalaVersion
import ru.d10xa.jadd.repository.MavenMetadata
import ru.d10xa.jadd.show.JaddFormatShowPrinter
import troubles.ArtifactTrouble
import troubles.WrongArtifactRaw
import ru.d10xa.jadd.versions.ScalaVersions
import ru.d10xa.jadd.versions.VersionFilter

final case class Artifact(
groupId: GroupId,
Expand All @@ -20,7 +18,6 @@ final case class Artifact(
shortcut: Option[String] = None,
scope: Option[Scope] = None,
repository: Option[String] = None,
mavenMetadata: Option[MavenMetadata] = None,
maybeScalaVersion: Option[ScalaVersion] = None,
availableVersions: Seq[Version] = Seq.empty[Version],
explicitScalaVersion: Boolean = false,
Expand Down Expand Up @@ -59,37 +56,10 @@ final case class Artifact(
artifactId.replace("%%", s"_${v.show}")
}

def merge(mavenMetadata: MavenMetadata): Artifact = {
val updated = this
.copy(
availableVersions = mavenMetadata.versions.reverse.map(Version(_)),
mavenMetadata = Some(mavenMetadata),
maybeScalaVersion =
this.maybeScalaVersion.orElse(mavenMetadata.maybeScalaVersion)
)
mavenMetadata.url.fold(updated)(updated.withMetadataUrl)
}

def withMetadataUrl(url: String): Artifact = {
val newMeta: Option[MavenMetadata] =
this.mavenMetadata
.map(meta => meta.copy(url = Some(url)))
.orElse(Some(MavenMetadata(url = Some(url))))
this.copy(mavenMetadata = newMeta)
}

def inlineScalaVersion: Artifact = Artifact.inlineScalaVersion(this)

def versionsForPrint: String = availableVersions.map(_.repr).mkString(", ")

def initLatestVersion(
versionFilter: VersionFilter = VersionFilter
): Artifact =
copy(
maybeVersion =
versionFilter.excludeNonRelease(availableVersions).headOption
)

}

object Artifact {
Expand Down
63 changes: 40 additions & 23 deletions src/main/scala/ru/d10xa/jadd/core/Loader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,33 @@ import cats.Functor
import cats.data.Ior
import cats.data.IorNel
import cats.effect.Sync
import com.typesafe.scalalogging.StrictLogging
import coursier.parse.RepositoryParser
import ru.d10xa.jadd.core.troubles.ArtifactTrouble
import ru.d10xa.jadd.pipelines.Pipeline
import ru.d10xa.jadd.shortcuts.ArtifactInfoFinder
import ru.d10xa.jadd.shortcuts.RepositoryShortcuts
import ru.d10xa.jadd.versions.ArtifactVersionsDownloader
import ru.d10xa.jadd.versions.VersionTools

trait Loader[F[_]] {
def load(ctx: Ctx): F[IorNel[ArtifactTrouble, List[Artifact]]]
def load(
ctx: Ctx,
versionTools: VersionTools[F]
): F[IorNel[ArtifactTrouble, List[Artifact]]]
}

class LiveLoader[F[_]: Sync] private (
artifactInfoFinder: ArtifactInfoFinder,
repositoryShortcuts: RepositoryShortcuts,
versionTools: VersionTools = VersionTools
) extends Loader[F] {
artifactInfoFinder: ArtifactInfoFinder
) extends Loader[F]
with StrictLogging {

override def load(ctx: Ctx): F[IorNel[ArtifactTrouble, List[Artifact]]] =
override def load(
ctx: Ctx,
versionTools: VersionTools[F]
): F[IorNel[ArtifactTrouble, List[Artifact]]] =
Pipeline
.extractArtifacts(ctx)
.flatMap(artifacts => loadByString(ctx, artifacts.toList))
.flatMap(artifacts => loadByString(ctx, artifacts.toList, versionTools))

def withScalaVersion[M[_]: Functor](
ctx: Ctx,
Expand All @@ -41,45 +47,56 @@ class LiveLoader[F[_]: Sync] private (

def loadByString(
ctx: Ctx,
artifacts: List[String]
artifacts: List[String],
versionTools: VersionTools[F]
): F[IorNel[ArtifactTrouble, List[Artifact]]] =
for {
unshorted <- Utils
.unshortAll(artifacts, artifactInfoFinder)
repositoriesUnshorted = ctx.config.repositories
.map(repositoryShortcuts.unshortRepository)
.toList
x = loadAllArtifacts(
repositoriesParsed <- RepositoryParser
.repositories(ctx.config.repositories)
.either match {
case Left(errs) =>
Sync[F].raiseError(
new RuntimeException(
s"Error parsing repositories:" + System.lineSeparator() +
errs.map(" " + _ + System.lineSeparator()).mkString
)
)
case Right(value) => Sync[F].pure(value.map(_.repr))
}
result <- loadAllArtifacts(
withScalaVersion(ctx, unshorted),
versionTools,
repositoriesUnshorted
repositoriesParsed
)
} yield x
} yield result

def loadAllArtifacts(
artifacts: Seq[Artifact],
versionTools: VersionTools,
versionTools: VersionTools[F],
repositories: Seq[String]
): IorNel[ArtifactTrouble, List[Artifact]] = {
): F[IorNel[ArtifactTrouble, List[Artifact]]] = {

val initial: IorNel[ArtifactTrouble, List[Artifact]] = Ior.Right(List())

artifacts
.map(
.traverse(
ArtifactVersionsDownloader
.loadArtifactVersions(_, repositories, versionTools)
)
.map(_.map(List(_)))
.foldLeft(initial)((a, b) => a.combine(b))
.map(
_.map(_.map(List(_)))
.foldLeft(initial)((a, b) => a.combine(b))
)
}

}

object LiveLoader {

def make[F[_]: Sync](
artifactInfoFinder: ArtifactInfoFinder,
repositoryShortcuts: RepositoryShortcuts
): Loader[F] = new LiveLoader[F](artifactInfoFinder, repositoryShortcuts)
artifactInfoFinder: ArtifactInfoFinder
): Loader[F] = new LiveLoader[F](artifactInfoFinder)

}
2 changes: 1 addition & 1 deletion src/main/scala/ru/d10xa/jadd/core/Utils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ object Utils extends StrictLogging {
): F[List[Artifact]] =
rawDependencies.flatTraverse(s => unshortOne(s, artifactInfoFinder))

def unshortOne[F[_]: Sync](
private def unshortOne[F[_]: Sync](
raw: String,
artifactInfoFinder: ArtifactInfoFinder
): F[List[Artifact]] =
Expand Down
37 changes: 37 additions & 0 deletions src/main/scala/ru/d10xa/jadd/coursier_/CoursierVersions.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package ru.d10xa.jadd.coursier_

import cats.Parallel
import cats.effect.ContextShift
import cats.effect.Sync
import coursier.Repository
import coursier.Versions
import coursier.cache.CachePolicy
import coursier.cache.FileCache
import coursier.core
import coursier.core.Module

trait CoursierVersions[F[_]] {
def versions(repositories: Seq[Repository], module: Module): F[core.Versions]
}

object CoursierVersions {
def make[F[_]: Sync: Parallel: ContextShift]: F[CoursierVersions[F]] =
Sync[F].delay(new CoursierVersions[F] {

implicit val S: coursier.util.Sync[F] = coursier.interop.cats
.coursierSyncFromCats(Sync[F], Parallel[F], ContextShift[F])

lazy val cache: FileCache[F] = FileCache[F]()(S).noCredentials
.withCachePolicies(Seq(CachePolicy.ForceDownload))

override def versions(
repositories: Seq[Repository],
module: Module): F[core.Versions] = {
Versions(cache)
.withRepositories(repositories)
.withModule(module)
.versions()
}

})
}
29 changes: 29 additions & 0 deletions src/main/scala/ru/d10xa/jadd/extensions.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ru.d10xa.jadd

import cats.data.NonEmptyList
import cats.data.Validated
import cats.data.Validated.Invalid
import cats.data.Validated.Valid
import coursier.util.ValidationNel

object extensions {

implicit class CoursierValidationNelExtension[L, R](
vnel: ValidationNel[L, R]) {
def toCatsValidatedNel: Validated[NonEmptyList[L], R] = vnel.either match {
case Left(h :: t) => Invalid(NonEmptyList(h, t))
case Right(value) => Valid(value)
}
}

implicit class ValidatedNelStringOps[A](
vnel: Validated[NonEmptyList[String], A]) {
import cats.syntax.foldable._
def joinNel: Validated[String, A] =
vnel.leftMap {
case NonEmptyList(head, Nil) => head
case nel => nel.mkString_("(", ", ", ")")
}
}

}
14 changes: 9 additions & 5 deletions src/main/scala/ru/d10xa/jadd/pipelines/Pipeline.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import ru.d10xa.jadd.core.troubles
import ru.d10xa.jadd.core.troubles.ArtifactTrouble
import ru.d10xa.jadd.core.troubles.handleTroubles
import ru.d10xa.jadd.versions.ScalaVersions
import ru.d10xa.jadd.versions.VersionTools

abstract class Pipeline[F[_]: Sync] extends StrictLogging {

Expand Down Expand Up @@ -62,13 +63,15 @@ abstract class Pipeline[F[_]: Sync] extends StrictLogging {
.getOrElse(ScalaVersions.defaultScalaVersion)

def run(
loader: Loader[F]
loader: Loader[F],
versionTools: VersionTools[F]
): F[Unit] = {
def loaded: F[IorNel[troubles.ArtifactTrouble, List[Artifact]]] =
for {
scalaVersion <- readScalaVersion()
res <- loader.load(
ctx.copy(meta = ProjectMeta(scalaVersion = Some(scalaVersion)))
ctx.copy(meta = ProjectMeta(scalaVersion = Some(scalaVersion))),
versionTools
)
} yield res
ctx.config.command match {
Expand All @@ -90,9 +93,10 @@ abstract class Pipeline[F[_]: Sync] extends StrictLogging {
val artifactsWithVersions = artifacts.map(_.inlineScalaVersion)
logger.info(ctx.config.showPrinter.mkString(artifactsWithVersions))
val stringsForPrint = artifactsWithVersions
.map(artifact =>
JaddFormatShowPrinter.withVersions
.single(artifact) + " // " + artifact.versionsForPrint
.map(
artifact =>
JaddFormatShowPrinter.withVersions
.single(artifact) + " // " + artifact.versionsForPrint
)
logger.debug(stringsForPrint.mkString("\n"))
}
Expand Down
37 changes: 0 additions & 37 deletions src/main/scala/ru/d10xa/jadd/repository/MavenMetadata.scala
Original file line number Diff line number Diff line change
@@ -1,37 +0,0 @@
package ru.d10xa.jadd.repository

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

import ru.d10xa.jadd.core.types.ScalaVersion
import ru.d10xa.jadd.xml.MavenMetadataVersionsRawReader

import scala.util.Try
import scala.xml.Elem

final case class MavenMetadata(
url: Option[String] = None,
repository: Option[String] = None,
versions: Seq[String] = Seq.empty,
lastUpdated: Option[String] = None,
maybeScalaVersion: Option[ScalaVersion] =
None // Metadata from newer to older (scala 2.12, 2.11..)
) {
lazy val lastUpdatedPretty: Option[String] =
lastUpdated.map(MavenMetadata.lastUpdatedPretty)
}

object MavenMetadata {
def readFromXml(from: MavenMetadata, root: Elem): MavenMetadata = from.copy(
versions = MavenMetadataVersionsRawReader.versions(root),
lastUpdated = MavenMetadataVersionsRawReader.lastUpdated(root)
)
def lastUpdatedPretty(lastUpdated: String): String = {
val formatIn = DateTimeFormatter.ofPattern("yyyyMMddHHmmss")
val formatOut = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
def prettyPrintDateFormat(dateStr: String): String =
Try(LocalDateTime.parse(dateStr, formatIn).format(formatOut))
.getOrElse(dateStr)
prettyPrintDateFormat(lastUpdated)
}
}
Loading

0 comments on commit 41d00bb

Please sign in to comment.