diff --git a/cache/src/main/scala/coursier/Cache.scala b/cache/src/main/scala/coursier/Cache.scala
index aa7d2f595..90e815fc4 100644
--- a/cache/src/main/scala/coursier/Cache.scala
+++ b/cache/src/main/scala/coursier/Cache.scala
@@ -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"""
$name0"""
+ }.mkString
+
+ val page =
+ s"""
+ |
+ |
+ |
+ |
+ |
+ |
+ """.stripMargin
+
+ Right(page)
+ } else {
val f0 = new File(f, ".directory")
if (f0.exists()) {
diff --git a/core/js/src/main/scala/coursier/core/compatibility/package.scala b/core/js/src/main/scala/coursier/core/compatibility/package.scala
index eebc41fa1..3b8659b5b 100644
--- a/core/js/src/main/scala/coursier/core/compatibility/package.scala
+++ b/core/js/src/main/scala/coursier/core/compatibility/package.scala
@@ -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
???
}
diff --git a/core/jvm/src/main/scala/coursier/core/compatibility/package.scala b/core/jvm/src/main/scala/coursier/core/compatibility/package.scala
index 11f052fe2..d4fbbd74c 100644
--- a/core/jvm/src/main/scala/coursier/core/compatibility/package.scala
+++ b/core/jvm/src/main/scala/coursier/core/compatibility/package.scala
@@ -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)
}
diff --git a/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala b/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala
index fd3d562b2..d10a9ae7f 100644
--- a/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala
+++ b/core/shared/src/main/scala/coursier/ivy/IvyRepository.scala
@@ -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
}
}
diff --git a/plugin/src/main/scala-2.10/coursier/FallbackDependenciesRepository.scala b/plugin/src/main/scala-2.10/coursier/FallbackDependenciesRepository.scala
index b2d495970..08018ffe7 100644
--- a/plugin/src/main/scala-2.10/coursier/FallbackDependenciesRepository.scala
+++ b/plugin/src/main/scala-2.10/coursier/FallbackDependenciesRepository.scala
@@ -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"))
+ }
+ }
}
}
diff --git a/plugin/src/sbt-test/sbt-coursier/from-wrong-url/build.sbt b/plugin/src/sbt-test/sbt-coursier/from-wrong-url/build.sbt
new file mode 100644
index 000000000..fbb442536
--- /dev/null
+++ b/plugin/src/sbt-test/sbt-coursier/from-wrong-url/build.sbt
@@ -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"
+}
diff --git a/plugin/src/sbt-test/sbt-coursier/from-wrong-url/project/plugins.sbt b/plugin/src/sbt-test/sbt-coursier/from-wrong-url/project/plugins.sbt
new file mode 100644
index 000000000..152225a9e
--- /dev/null
+++ b/plugin/src/sbt-test/sbt-coursier/from-wrong-url/project/plugins.sbt
@@ -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)
+}
diff --git a/plugin/src/sbt-test/sbt-coursier/from-wrong-url/src/main/scala/Main.scala b/plugin/src/sbt-test/sbt-coursier/from-wrong-url/src/main/scala/Main.scala
new file mode 100644
index 000000000..c9401ff3e
--- /dev/null
+++ b/plugin/src/sbt-test/sbt-coursier/from-wrong-url/src/main/scala/Main.scala
@@ -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"))
+}
diff --git a/plugin/src/sbt-test/sbt-coursier/from-wrong-url/test b/plugin/src/sbt-test/sbt-coursier/from-wrong-url/test
new file mode 100644
index 000000000..2182f57b0
--- /dev/null
+++ b/plugin/src/sbt-test/sbt-coursier/from-wrong-url/test
@@ -0,0 +1,3 @@
+$ delete output
+> run
+$ exists output