From bddf67cc17cdaf5873c9a97e1e455c41c62645eb Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sat, 22 Jul 2017 17:29:25 +0200 Subject: [PATCH 1/7] Always try to get artifacts corresponding to packaging --- .../scala/coursier/core/Definitions.scala | 3 + .../scala/coursier/maven/MavenSource.scala | 74 +++++++++++-------- tests/metadata | 2 +- .../extensions/1.0.0-alpha3 | 10 +++ .../scala/coursier/test/CentralTests.scala | 27 +++++++ 5 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 tests/shared/src/test/resources/resolutions/android.arch.lifecycle/extensions/1.0.0-alpha3 diff --git a/core/shared/src/main/scala/coursier/core/Definitions.scala b/core/shared/src/main/scala/coursier/core/Definitions.scala index dde61eac1..aa37c8f55 100644 --- a/core/shared/src/main/scala/coursier/core/Definitions.scala +++ b/core/shared/src/main/scala/coursier/core/Definitions.scala @@ -64,6 +64,9 @@ final case class Attributes( ) { def publication(name: String, ext: String): Publication = Publication(name, `type`, ext, classifier) + + def isEmpty: Boolean = + `type`.isEmpty && classifier.isEmpty } final case class Project( diff --git a/core/shared/src/main/scala/coursier/maven/MavenSource.scala b/core/shared/src/main/scala/coursier/maven/MavenSource.scala index 20c64dad0..bed974db4 100644 --- a/core/shared/src/main/scala/coursier/maven/MavenSource.scala +++ b/core/shared/src/main/scala/coursier/maven/MavenSource.scala @@ -19,8 +19,9 @@ final case class MavenSource( overrideClassifiers: Option[Seq[String]] ): Seq[Artifact] = { - val packagingTpeMap = project.packagingOpt - .filter(_ != Pom.relocatedPackaging) + val packagingOpt = project.packagingOpt.filter(_ != Pom.relocatedPackaging) + + val packagingTpeMap = packagingOpt .map { packaging => (MavenSource.typeDefaultClassifier(packaging), MavenSource.typeExtension(packaging)) -> packaging } @@ -67,7 +68,18 @@ final case class MavenSource( ) } - lazy val defaultPublication = { + lazy val defaultPublications = { + + val packagingPublicationOpt = packagingOpt + .filter(_ => dependency.attributes.isEmpty) + .map { packaging => + Publication( + dependency.module.name, + packaging, + MavenSource.typeExtension(packaging), + MavenSource.typeDefaultClassifier(packaging) + ) + } val type0 = if (dependency.attributes.`type`.isEmpty) "jar" else dependency.attributes.`type` @@ -84,41 +96,41 @@ final case class MavenSource( MavenSource.classifierExtensionDefaultTypeOpt(classifier, ext).getOrElse(ext) ) - Publication( - dependency.module.name, - tpe, - ext, - classifier - ) + val pubs = packagingPublicationOpt.toSeq :+ + Publication( + dependency.module.name, + tpe, + ext, + classifier + ) + + pubs.distinct } - overrideClassifiers match { - case Some(classifiers) => - - classifiers - .map { classifier => - if (classifier == dependency.attributes.classifier) - defaultPublication - else { - val ext = "jar" - val tpe = packagingTpeMap.getOrElse( - (classifier, ext), - MavenSource.classifierExtensionDefaultTypeOpt(classifier, ext).getOrElse(ext) - ) + overrideClassifiers + .fold(defaultPublications) { classifiers => + classifiers.flatMap { classifier => + if (classifier == dependency.attributes.classifier) + defaultPublications + else { + val ext = "jar" + val tpe = packagingTpeMap.getOrElse( + (classifier, ext), + MavenSource.classifierExtensionDefaultTypeOpt(classifier, ext).getOrElse(ext) + ) + Seq( Publication( dependency.module.name, tpe, ext, classifier ) - } + ) } - .map(artifactWithExtra) - - case None => - Seq(defaultPublication).map(artifactWithExtra) - } + } + } + .map(artifactWithExtra) } private val types = Map("sha1" -> "SHA-1", "md5" -> "MD5", "asc" -> "sig") @@ -290,14 +302,14 @@ final case class MavenSource( } val defaultPublications = artifactsUnknownPublications(dependency, project, overrideClassifiers) + .map(makeOptional) if (project.publications.isEmpty) defaultPublications else { val listedPublications = artifactsKnownPublications(dependency, project, overrideClassifiers) val listedUrls = listedPublications.map(_.url).toSet - val defaultPublications0 = defaultPublications.map(makeOptional) - val defaultPublicationsMap = defaultPublications0 + val defaultPublicationsMap = defaultPublications .map(a => a.url -> a) .toMap val listedPublications0 = listedPublications.map { a => @@ -305,7 +317,7 @@ final case class MavenSource( .get(a.url) .fold(a)(merge(a, _)) } - val extraPublications = defaultPublications0 + val extraPublications = defaultPublications .filter(a => !listedUrls(a.url)) listedPublications0 ++ extraPublications diff --git a/tests/metadata b/tests/metadata index 93eccec4f..6b2578a25 160000 --- a/tests/metadata +++ b/tests/metadata @@ -1 +1 @@ -Subproject commit 93eccec4ffd1719586b6f1e1dddefcbea6722e7d +Subproject commit 6b2578a25220930e60b505b90e636092757d6397 diff --git a/tests/shared/src/test/resources/resolutions/android.arch.lifecycle/extensions/1.0.0-alpha3 b/tests/shared/src/test/resources/resolutions/android.arch.lifecycle/extensions/1.0.0-alpha3 new file mode 100644 index 000000000..effcc9c3c --- /dev/null +++ b/tests/shared/src/test/resources/resolutions/android.arch.lifecycle/extensions/1.0.0-alpha3 @@ -0,0 +1,10 @@ +android.arch.core:core:1.0.0-alpha3:compile +android.arch.lifecycle:common:1.0.0-alpha3:compile +android.arch.lifecycle:extensions:1.0.0-alpha3:compile +android.arch.lifecycle:runtime:1.0.0-alpha3:compile +com.android.support:support-annotations:25.3.1:compile +com.android.support:support-compat:25.3.1:compile +com.android.support:support-core-ui:25.3.1:compile +com.android.support:support-core-utils:25.3.1:compile +com.android.support:support-fragment:25.3.1:compile +com.android.support:support-media-compat:25.3.1:compile \ No newline at end of file diff --git a/tests/shared/src/test/scala/coursier/test/CentralTests.scala b/tests/shared/src/test/scala/coursier/test/CentralTests.scala index bf91d54ea..53a8252bc 100644 --- a/tests/shared/src/test/scala/coursier/test/CentralTests.scala +++ b/tests/shared/src/test/scala/coursier/test/CentralTests.scala @@ -822,6 +822,33 @@ abstract class CentralTests extends TestSuite { } } } + + 'packagingTpe - { + val mod = Module("android.arch.lifecycle", "extensions") + val ver = "1.0.0-alpha3" + + val extraRepo = MavenRepository("https://maven.google.com") + + * - resolutionCheck(mod, ver, extraRepos = Seq(extraRepo)) + + * - withArtifacts(mod, ver, "*", extraRepos = Seq(extraRepo), transitive = true) { artifacts => + val urls = artifacts.map(_.url).toSet + val expectedUrls = Set( + "https://maven.google.com/com/android/support/support-fragment/25.3.1/support-fragment-25.3.1.aar", + "https://maven.google.com/android/arch/core/core/1.0.0-alpha3/core-1.0.0-alpha3.aar", + "https://maven.google.com/android/arch/lifecycle/runtime/1.0.0-alpha3/runtime-1.0.0-alpha3.aar", + "https://maven.google.com/android/arch/lifecycle/extensions/1.0.0-alpha3/extensions-1.0.0-alpha3.aar", + "https://maven.google.com/com/android/support/support-compat/25.3.1/support-compat-25.3.1.aar", + "https://maven.google.com/com/android/support/support-media-compat/25.3.1/support-media-compat-25.3.1.aar", + "https://maven.google.com/com/android/support/support-core-ui/25.3.1/support-core-ui-25.3.1.aar", + "https://maven.google.com/com/android/support/support-core-utils/25.3.1/support-core-utils-25.3.1.aar", + "https://maven.google.com/com/android/support/support-annotations/25.3.1/support-annotations-25.3.1.jar", + "https://maven.google.com/android/arch/lifecycle/common/1.0.0-alpha3/common-1.0.0-alpha3.jar" + ) + + assert(expectedUrls.forall(urls)) + } + } } } From ea8927d7b2cbb369714ef8efc811154e0d621b9a Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sat, 22 Jul 2017 17:29:26 +0200 Subject: [PATCH 2/7] Don't unnecesarily mark some artifacts as optional --- core/shared/src/main/scala/coursier/maven/MavenSource.scala | 2 +- tests/shared/src/test/scala/coursier/test/CentralTests.scala | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/core/shared/src/main/scala/coursier/maven/MavenSource.scala b/core/shared/src/main/scala/coursier/maven/MavenSource.scala index bed974db4..df1b09dfe 100644 --- a/core/shared/src/main/scala/coursier/maven/MavenSource.scala +++ b/core/shared/src/main/scala/coursier/maven/MavenSource.scala @@ -251,7 +251,7 @@ final case class MavenSource( else if (dependency.attributes.`type`.nonEmpty) enrichedPublications.collect { case p - if p.publication.classifier.isEmpty && ( + if (p.publication.classifier.isEmpty || p.publication.classifier == MavenSource.typeDefaultClassifier(dependency.attributes.`type`)) && ( p.publication.`type` == dependency.attributes.`type` || (p.publication.ext == dependency.attributes.`type` && project.packagingOpt.toSeq.contains(p.publication.`type`)) // wow ) => diff --git a/tests/shared/src/test/scala/coursier/test/CentralTests.scala b/tests/shared/src/test/scala/coursier/test/CentralTests.scala index 53a8252bc..392d36e61 100644 --- a/tests/shared/src/test/scala/coursier/test/CentralTests.scala +++ b/tests/shared/src/test/scala/coursier/test/CentralTests.scala @@ -569,6 +569,7 @@ abstract class CentralTests extends TestSuite { val zookeeperTestArtifact = zookeeperTestArtifacts.head + assert(!isActualCentral || !zookeeperTestArtifact.isOptional) assert(zookeeperTestArtifact.attributes.`type` == "test-jar") assert(zookeeperTestArtifact.attributes.classifier == "tests") zookeeperTestArtifact.url.endsWith("-tests.jar") From d3bedc838fa438742039b4fb693b05791d9a668a Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sat, 22 Jul 2017 17:29:27 +0200 Subject: [PATCH 3/7] Fix updateSbtClassifiers --- .../src/main/scala/coursier/FromSbt.scala | 28 +++++++++++++ .../src/main/scala/coursier/Tasks.scala | 26 ++----------- .../update-sbt-classifiers/build.sbt | 39 +++++++++++++++++++ .../project/plugins.sbt | 11 ++++++ .../src/main/scala-2.10/Compatibility.scala | 8 ++++ .../src/main/scala-2.12/Compatibility.scala | 1 + .../sbt-coursier/update-sbt-classifiers/test | 1 + 7 files changed, 92 insertions(+), 22 deletions(-) create mode 100644 sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/build.sbt create mode 100644 sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/project/plugins.sbt create mode 100644 sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/project/src/main/scala-2.10/Compatibility.scala create mode 100644 sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/project/src/main/scala-2.12/Compatibility.scala create mode 100644 sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/test diff --git a/sbt-coursier/src/main/scala/coursier/FromSbt.scala b/sbt-coursier/src/main/scala/coursier/FromSbt.scala index 9c50d9aa9..c603f106b 100644 --- a/sbt-coursier/src/main/scala/coursier/FromSbt.scala +++ b/sbt-coursier/src/main/scala/coursier/FromSbt.scala @@ -103,6 +103,34 @@ object FromSbt { (module0, version, url, module.isChanging) } + def sbtClassifiersProject( + cm: GetClassifiersModule, + scalaVersion: String, + scalaBinaryVersion: String + ) = { + + val p = FromSbt.project( + cm.id, + cm.dependencies, + cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap, + scalaVersion, + scalaBinaryVersion + ) + + // for w/e reasons, the dependencies sometimes don't land in the right config above + // this is a loose attempt at fixing that + cm.configurations match { + case Seq(cfg) => + p.copy( + dependencies = p.dependencies.map { + case (_, d) => (cfg.name, d) + } + ) + case _ => + p + } + } + def project( projectID: ModuleID, allDependencies: Seq[ModuleID], diff --git a/sbt-coursier/src/main/scala/coursier/Tasks.scala b/sbt-coursier/src/main/scala/coursier/Tasks.scala index fafe42b19..5d4551e97 100644 --- a/sbt-coursier/src/main/scala/coursier/Tasks.scala +++ b/sbt-coursier/src/main/scala/coursier/Tasks.scala @@ -550,13 +550,7 @@ object Tasks { val (currentProject, fallbackDependencies, configGraphs) = if (sbtClassifiers) { - val proj = FromSbt.project( - cm.id, - cm.dependencies, - cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap, - sv, - sbv - ) + val proj = FromSbt.sbtClassifiersProject(cm, sv, sbv) val fallbackDeps = FromSbt.fallbackDependencies( cm.dependencies, @@ -1112,13 +1106,7 @@ object Tasks { val currentProject = if (sbtClassifiers) - FromSbt.project( - cm.id, - cm.dependencies, - cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap, - sv, - sbv - ) + FromSbt.sbtClassifiersProject(cm, sv, sbv) else proj.copy(publications = publications) @@ -1155,7 +1143,7 @@ object Tasks { val configs = if (withClassifiers && sbtClassifiers) - cm.configurations.map(c => c.name -> Set.empty[String]).toMap + cm.configurations.map(c => c.name -> Set(c.name)).toMap else shadedConfigOpt.fold(configs0) { case (baseConfig, shadedConfig) => @@ -1277,13 +1265,7 @@ object Tasks { val currentProject = if (sbtClassifiers) - FromSbt.project( - cm.id, - cm.dependencies, - cm.configurations.map(cfg => cfg.name -> cfg.extendsConfigs.map(_.name)).toMap, - sv, - sbv - ) + FromSbt.sbtClassifiersProject(cm, sv, sbv) else proj.copy(publications = publications) diff --git a/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/build.sbt b/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/build.sbt new file mode 100644 index 000000000..77feb59e6 --- /dev/null +++ b/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/build.sbt @@ -0,0 +1,39 @@ + +import Compatibility._ + +scalaVersion := appConfiguration.value.provider.scalaProvider.version + +lazy val updateSbtClassifiersCheck = TaskKey[Unit]("updateSbtClassifiersCheck") + +updateSbtClassifiersCheck := { + + val configReport = updateSbtClassifiers + .value + .configuration(Default) + .getOrElse { + throw new Exception( + "default configuration not found in updateSbtClassifiers report" + ) + } + + def artifacts(org: String, name: String) = configReport + .modules + .collect { + case moduleReport + if moduleReport.module.organization == org && + moduleReport.module.name == name => + moduleReport.artifacts + } + .toSeq + .flatten + + def ensureHasArtifact(org: String, name: String) = + assert( + artifacts(org, name).exists(_._2.getName.endsWith("-sources.jar")), + s"$org:$name not found" + ) + + ensureHasArtifact("org.scala-lang", "scala-library") + ensureHasArtifact("io.get-coursier", "coursier_" + scalaBinaryVersion.value) + ensureHasArtifact("io.get-coursier", "sbt-coursier") +} diff --git a/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/project/plugins.sbt b/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/project/plugins.sbt new file mode 100644 index 000000000..8d902e4dc --- /dev/null +++ b/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/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) +} \ No newline at end of file diff --git a/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/project/src/main/scala-2.10/Compatibility.scala b/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/project/src/main/scala-2.10/Compatibility.scala new file mode 100644 index 000000000..8824f1209 --- /dev/null +++ b/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/project/src/main/scala-2.10/Compatibility.scala @@ -0,0 +1,8 @@ +object Compatibility { + + implicit class UpdateReportOps(val rep: sbt.UpdateReport) extends AnyVal { + def configuration(conf: sbt.Configuration) = + rep.configuration(conf.name) + } + +} diff --git a/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/project/src/main/scala-2.12/Compatibility.scala b/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/project/src/main/scala-2.12/Compatibility.scala new file mode 100644 index 000000000..19835e1be --- /dev/null +++ b/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/project/src/main/scala-2.12/Compatibility.scala @@ -0,0 +1 @@ +object Compatibility diff --git a/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/test b/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/test new file mode 100644 index 000000000..f6351a4d9 --- /dev/null +++ b/sbt-coursier/src/sbt-test/sbt-coursier/update-sbt-classifiers/test @@ -0,0 +1 @@ +> updateSbtClassifiersCheck From ef59fb5e49f927b158cd2f9212c3f01fd986f1a2 Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sat, 22 Jul 2017 17:29:28 +0200 Subject: [PATCH 4/7] Add small test of the code ensuring a module isn't fetched concurrently twice --- .../test/ResolutionProcessTests.scala | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 tests/jvm/src/test/scala/coursier/test/ResolutionProcessTests.scala diff --git a/tests/jvm/src/test/scala/coursier/test/ResolutionProcessTests.scala b/tests/jvm/src/test/scala/coursier/test/ResolutionProcessTests.scala new file mode 100644 index 000000000..6fa1039cc --- /dev/null +++ b/tests/jvm/src/test/scala/coursier/test/ResolutionProcessTests.scala @@ -0,0 +1,72 @@ +package coursier.test + +import java.util.concurrent.ConcurrentHashMap + +import coursier.{Fetch, Module} +import coursier.core.ResolutionProcess +import utest._ + +import scala.collection.JavaConverters._ +import scala.concurrent.duration.DurationInt +import scalaz.{-\/, \/-} +import scalaz.concurrent.Task + +object ResolutionProcessTests extends TestSuite { + + val tests = TestSuite { + + 'fetchAll - { + + // check that tasks fetching different versions of the same module are spawned sequentially + // rather than all at once + def check(extra: Int): Unit = { + + val mod = Module("org", "name") + val modVers = (1 to (9 + extra)) + .map(_.toString) + .map((mod, _)) + + val called = new ConcurrentHashMap[String, Unit] + + val fetch: Fetch.Metadata[Task] = { + + case Seq((`mod`, "9")) => + // never calls the callback + Task.async { _ => + called.put("9", ()) + () + } + + case Seq(mv @ (`mod`, v)) => + Task.async { cb => + called.put(v, ()) + cb(\/-(Seq((mv, -\/(Seq("w/e")))))) + } + + case _ => sys.error(s"Cannot happen ($modVers)") + } + + val res = ResolutionProcess.fetchAll(modVers, fetch) + .timed(1.second) + .attempt + .unsafePerformSync + + // must have timed out + assert(res.swap.exists[Throwable] { case _: java.util.concurrent.TimeoutException => true; case _ => false }) + + val called0 = called.asScala.iterator.map(_._1).toSet + val expectedCalled = (0 to extra) + .map(9 + _) + .map(_.toString) + .toSet + assert(called0 == expectedCalled) + } + + * - check(0) + * - check(1) + * - check(3) + } + + } + +} From 862169c6bb1fc9becf5526e24dfbc446fe6c8e49 Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sat, 22 Jul 2017 17:29:29 +0200 Subject: [PATCH 5/7] Add more guarantees that a same module can't be downloaded concurrently traverse called in ResolutionProcess.fetchAll relies on Applicative, so doesn't guarantee that the module groups will be fetched one after the other. The Applicative instance of scalaz.concurrent.Task doesn't parallelize the tasks by default, so it works fine here. But that extra security ensures that code can be fine with other monads. --- .../scala/coursier/core/ResolutionProcess.scala | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/core/shared/src/main/scala/coursier/core/ResolutionProcess.scala b/core/shared/src/main/scala/coursier/core/ResolutionProcess.scala index 7d4452f98..0f3f5ac75 100644 --- a/core/shared/src/main/scala/coursier/core/ResolutionProcess.scala +++ b/core/shared/src/main/scala/coursier/core/ResolutionProcess.scala @@ -3,9 +3,8 @@ package core import scala.annotation.tailrec import scala.language.higherKinds - -import scalaz.{Monad, -\/, \/-} -import scalaz.Scalaz.{ToFunctorOps, ToTraverseOps, vectorInstance} +import scalaz.{-\/, Monad, \/, \/-} +import scalaz.Scalaz.{ToFunctorOps, ToBindOps, ToTraverseOps, vectorInstance} sealed abstract class ResolutionProcess { @@ -166,7 +165,10 @@ object ResolutionProcess { Missing(resolution0.missingFromCache.toSeq, resolution0, apply) } - private def fetchAll[F[_]](modVers: Seq[(Module, String)], fetch: Fetch.Metadata[F])(implicit F: Monad[F]) = { + private[coursier] def fetchAll[F[_]]( + modVers: Seq[(Module, String)], + fetch: Fetch.Metadata[F] + )(implicit F: Monad[F]): F[Vector[((Module, String), Seq[String] \/ (Artifact.Source, Project))]] = { def uniqueModules(modVers: Seq[(Module, String)]): Stream[Seq[(Module, String)]] = { @@ -191,8 +193,11 @@ object ResolutionProcess { uniqueModules(modVers) .toVector - .traverse(fetch) - .map(_.flatten) + .foldLeft(F.point(Vector.empty[((Module, String), Seq[String] \/ (Artifact.Source, Project))])) { + (acc, l) => + for (v <- acc; e <- fetch(l)) + yield v ++ e + } } } From 4ed2e2a26173eb37b0bac7ccfd933e5d31361c81 Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sat, 22 Jul 2017 17:29:30 +0200 Subject: [PATCH 6/7] Tweak display Simply display an empty progress bar when size is unknown --- cache/src/main/scala/coursier/TermDisplay.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cache/src/main/scala/coursier/TermDisplay.scala b/cache/src/main/scala/coursier/TermDisplay.scala index b241c6c4a..7ea1b7f25 100644 --- a/cache/src/main/scala/coursier/TermDisplay.scala +++ b/cache/src/main/scala/coursier/TermDisplay.scala @@ -74,8 +74,7 @@ object TermDisplay { val start = actualFraction match { case None => - val elem = if (watching) "." else "?" - s" [ $elem ] " + " [ ] " case Some(frac) => val elem = if (watching) "." else "#" From 9dfed940538a510c9f8dcab22339ab8c34640b62 Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sat, 22 Jul 2017 17:29:33 +0200 Subject: [PATCH 7/7] Add short syntax for jitpack repo --- core/shared/src/main/scala/coursier/util/Parse.scala | 2 ++ tests/shared/src/test/scala/coursier/test/ParseTests.scala | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/core/shared/src/main/scala/coursier/util/Parse.scala b/core/shared/src/main/scala/coursier/util/Parse.scala index b8c28731d..270a427e3 100644 --- a/core/shared/src/main/scala/coursier/util/Parse.scala +++ b/core/shared/src/main/scala/coursier/util/Parse.scala @@ -207,6 +207,8 @@ object Parse { ).right else if (s.startsWith("ivy:")) IvyRepository.parse(s.stripPrefix("ivy:")) + else if (s == "jitpack") + MavenRepository("https://jitpack.io").right else MavenRepository(s).right diff --git a/tests/shared/src/test/scala/coursier/test/ParseTests.scala b/tests/shared/src/test/scala/coursier/test/ParseTests.scala index aa625a13d..510304771 100644 --- a/tests/shared/src/test/scala/coursier/test/ParseTests.scala +++ b/tests/shared/src/test/scala/coursier/test/ParseTests.scala @@ -42,5 +42,10 @@ object ParseTests extends TestSuite { val res = Parse.repository("typesafe:releases") assert(res.exists(isMavenRepo)) } + + "jitpack" - { + val res = Parse.repository("jitpack") + assert(res.exists(isMavenRepo)) + } } }