More reliable fallback dependencies

Should fix the jrudolph/sbt-dependency-graph case of
https://gist.github.com/paulp/62eaca1850904137959ad9121cce6b15
This commit is contained in:
Alexandre Archambault 2016-08-22 00:19:49 +02:00
parent bbd367d14e
commit c17cf67734
No known key found for this signature in database
GPG Key ID: 14640A6839C263A9
9 changed files with 121 additions and 32 deletions

View File

@ -903,9 +903,32 @@ object Cache {
val res = if (f.exists()) {
if (f.isDirectory) {
if (artifact.url.startsWith("file:"))
Left("Not implemented: listing of local directories")
else {
if (artifact.url.startsWith("file:")) {
val elements = f.listFiles().map { c =>
val name = c.getName
val name0 = if (c.isDirectory)
name + "/"
else
name
s"""<li><a href="$name0">$name0</a></li>"""
}.mkString
val page =
s"""<!DOCTYPE html>
|<html>
|<head></head>
|<body>
|<ul>
|$elements
|</ul>
|</body>
|</html>
""".stripMargin
Right(page)
} else {
val f0 = new File(f, ".directory")
if (f0.exists()) {

View File

@ -93,7 +93,12 @@ package object compatibility {
def encodeURIComponent(s: String): String =
g.encodeURIComponent(s).asInstanceOf[String]
def listWebPageSubDirectories(page: String): Seq[String] = {
def listWebPageSubDirectories(url: String, page: String): Seq[String] = {
// TODO
???
}
def listWebPageFiles(url: String, page: String): Seq[String] = {
// TODO
???
}

View File

@ -56,17 +56,25 @@ package object compatibility {
def encodeURIComponent(s: String): String =
new java.net.URI(null, null, null, -1, s, null, null) .toASCIIString
def listWebPageSubDirectories(page: String): Seq[String] =
def listWebPageDirectoryElements(url: String, page: String, directories: Boolean): Seq[String] =
Jsoup.parse(page)
.select("a[href~=[^/]*/]")
.select("a")
.asScala
.toVector
.map { elem =>
elem
.attr("href")
.stripPrefix(":") // bintray typically prepends these
.stripSuffix("/")
.map(_.attr("href"))
.collect {
case elem if elem.nonEmpty && elem.endsWith("/") == directories =>
elem
.stripSuffix("/")
.stripPrefix(url)
.stripPrefix(":") // bintray typically prepends these
}
.filter(n => n != "." && n != "..")
.filter(n => !n.contains("/") && n != "." && n != "..")
def listWebPageSubDirectories(url: String, page: String): Seq[String] =
listWebPageDirectoryElements(url, page, directories = true)
def listWebPageFiles(url: String, page: String): Seq[String] =
listWebPageDirectoryElements(url, page, directories = false)
}

View File

@ -147,8 +147,8 @@ case class IvyRepository(
s"Don't know how to list revisions of ${metadataPattern.string}".left
}
def fromWebPage(s: String) = {
val subDirs = coursier.core.compatibility.listWebPageSubDirectories(s)
def fromWebPage(url: String, s: String) = {
val subDirs = coursier.core.compatibility.listWebPageSubDirectories(url, s)
val versions = subDirs.map(Parse.version).collect { case Some(v) => v }
val versionsInItv = versions.filter(itv.contains)
@ -173,7 +173,7 @@ case class IvyRepository(
for {
url <- EitherT(F.point(listingUrl))
s <- fetch(artifactFor(url))
res <- fromWebPage(s)
res <- fromWebPage(url, s)
} yield res
}
}

View File

@ -8,7 +8,7 @@ case class FallbackDependenciesRepository(
fallbacks: Map[(Module, String), (URL, Boolean)]
) extends Repository {
private val source = new Artifact.Source {
private val source: Artifact.Source = new Artifact.Source {
def artifacts(
dependency: Dependency,
project: Project,
@ -35,22 +35,41 @@ case class FallbackDependenciesRepository(
EitherT.left(F.point("No fallback URL found"))
case Some((url, _)) =>
val proj = Project(
module,
version,
Nil,
Map.empty,
None,
Nil,
Nil,
Nil,
None,
None,
None,
Nil,
Info.empty
)
EitherT.right(F.point((source, proj)))
val urlStr = url.toExternalForm
val idx = urlStr.lastIndexOf('/')
if (idx < 0 || urlStr.endsWith("/"))
EitherT.left(F.point(s"$url doesn't point to a file"))
else {
val (dirUrlStr, fileName) = urlStr.splitAt(idx + 1)
fetch(Artifact(dirUrlStr, Map.empty, Map.empty, Attributes("", ""), changing = true, None)).flatMap { listing =>
val files = coursier.core.compatibility.listWebPageFiles(dirUrlStr, listing)
if (files.contains(fileName)) {
val proj = Project(
module,
version,
Nil,
Map.empty,
None,
Nil,
Nil,
Nil,
None,
None,
None,
Nil,
Info.empty
)
EitherT.right(F.point((source, proj)))
} else
EitherT.left(F.point(s"$fileName not found under $dirUrlStr"))
}
}
}
}

View File

@ -0,0 +1,7 @@
scalaVersion := "2.11.8"
// keeping the default cache policies here
libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.2" from {
"https://repo1.maven.org/maven2/com/chuusai/shapeless_2.11/2.3.242/shapeless_2.11-2.3.242.jar"
}

View File

@ -0,0 +1,11 @@
{
val pluginVersion = sys.props.getOrElse(
"plugin.version",
throw new RuntimeException(
"""|The system property 'plugin.version' is not defined.
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin
)
)
addSbtPlugin("io.get-coursier" % "sbt-coursier" % pluginVersion)
}

View File

@ -0,0 +1,13 @@
import java.io.File
import java.nio.file.Files
import shapeless._
object Main extends App {
case class CC(s: String)
val cc = CC("OK")
val l = Generic[CC].to(cc)
val msg = l.head
Files.write(new File("output").toPath, msg.getBytes("UTF-8"))
}

View File

@ -0,0 +1,3 @@
$ delete output
> run
$ exists output