diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/CoursierConfiguration.scala b/modules/lm-coursier/src/main/scala/lmcoursier/CoursierConfiguration.scala index 45ea1b886..34fa1282e 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/CoursierConfiguration.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/CoursierConfiguration.scala @@ -49,6 +49,8 @@ import scala.concurrent.duration.Duration ttl: Option[Duration] = CacheDefaults.ttl, checksums: Vector[Option[String]] = CacheDefaults.checksums.to[Vector], cachePolicies: Vector[CachePolicy] = CacheDefaults.cachePolicies.to[Vector].map(FromCoursier.cachePolicy), + @since + missingOk: Boolean = false, ) { def withLog(log: Logger): CoursierConfiguration = diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala b/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala index dedd09910..0adb719f4 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/CoursierDependencyResolution.scala @@ -159,7 +159,8 @@ class CoursierDependencyResolution(conf: CoursierConfiguration) extends Dependen .withForceVersion(conf.forceVersions.map { case (k, v) => (ToCoursier.module(k), v) }.toMap) .withTypelevel(typelevel) .withReconciliation(ToCoursier.reconciliation(conf.reconciliation)), - strictOpt = conf.strict.map(ToCoursier.strict) + strictOpt = conf.strict.map(ToCoursier.strict), + missingOk = conf.missingOk, ) def artifactsParams(resolutions: Map[Set[Configuration], Resolution]): ArtifactsParams = @@ -212,7 +213,6 @@ class CoursierDependencyResolution(conf: CoursierConfiguration) extends Dependen val updateParams0 = updateParams(resolutions, artifacts) UpdateRun.update(updateParams0, verbosityLevel, log) } - e.left.map(unresolvedWarningOrThrow(uwconfig, _)) } diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionParams.scala b/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionParams.scala index 2dcdf4837..b262b3414 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionParams.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionParams.scala @@ -26,7 +26,8 @@ final case class ResolutionParams( cache: coursier.cache.FileCache[Task], parallel: Int, params: coursier.params.ResolutionParams, - strictOpt: Option[Strict] + strictOpt: Option[Strict], + missingOk: Boolean, ) { val fallbackDependenciesRepositories = diff --git a/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionRun.scala b/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionRun.scala index ee1425f13..dc34688e8 100644 --- a/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionRun.scala +++ b/modules/lm-coursier/src/main/scala/lmcoursier/internal/ResolutionRun.scala @@ -115,7 +115,10 @@ object ResolutionRun { } ) ) - .either() + .either() match { + case Left(err) if params.missingOk => Right(err.resolution) + case others => others + } } } diff --git a/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/CoursierPlugin.scala b/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/CoursierPlugin.scala index 953fa2df0..7ccb8b98e 100644 --- a/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/CoursierPlugin.scala +++ b/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/CoursierPlugin.scala @@ -166,7 +166,10 @@ object CoursierPlugin extends AutoPlugin { coursierSbtClassifiersModule := classifiersModule.in(updateSbtClassifiers).value, coursierConfigurations := InputsTasks.coursierConfigurationsTask(None).value, coursierParentProjectCache := InputsTasks.parentProjectCacheTask.value, - coursierResolutions := ResolutionTasks.resolutionsTask().value, + coursierResolutions := (Def.taskDyn { + val missingOk = updateConfiguration.value.missingOk + ResolutionTasks.resolutionsTask(missingOk = missingOk) + }).value, Keys.actualCoursierResolution := { val config = Configuration(Compile.name) @@ -181,9 +184,13 @@ object CoursierPlugin extends AutoPlugin { sys.error(s"Resolution for configuration $config not found") } }, - coursierSbtClassifiersResolution := ResolutionTasks.resolutionsTask( - sbtClassifiers = true - ).value.head._2 + coursierSbtClassifiersResolution := (Def.taskDyn { + val missingOk = (updateConfiguration in updateSbtClassifiers).value.missingOk + ResolutionTasks.resolutionsTask( + sbtClassifiers = true, + missingOk = missingOk, + ) + }).value.head._2 ) override lazy val buildSettings = super.buildSettings ++ Seq( diff --git a/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/ResolutionTasks.scala b/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/ResolutionTasks.scala index 1b9f8392b..ef7e923ba 100644 --- a/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/ResolutionTasks.scala +++ b/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/ResolutionTasks.scala @@ -17,7 +17,8 @@ import sbt.Keys._ object ResolutionTasks { def resolutionsTask( - sbtClassifiers: Boolean = false + sbtClassifiers: Boolean = false, + missingOk: Boolean = false, ): Def.Initialize[sbt.Task[Map[Set[Configuration], coursier.Resolution]]] = { val currentProjectTask: sbt.Def.Initialize[sbt.Task[(Project, Seq[FallbackDependency], Seq[Set[Configuration]])]] = @@ -154,7 +155,8 @@ object ResolutionTasks { .withForceVersion(userForceVersions.map { case (k, v) => (ToCoursier.module(k), v) }.toMap) .withTypelevel(typelevel) .addReconciliation(versionReconciliations0: _*), - strictOpt = strictOpt + strictOpt = strictOpt, + missingOk = missingOk, ), verbosityLevel, log diff --git a/modules/sbt-coursier/src/sbt-test/shared-2/missingok/build.sbt b/modules/sbt-coursier/src/sbt-test/shared-2/missingok/build.sbt new file mode 100644 index 000000000..886ddeebb --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-2/missingok/build.sbt @@ -0,0 +1,40 @@ +scalaVersion := "2.13.2" +libraryDependencies ++= Seq( + "com.chuusai" %% "shapeless" % "2.3.3", + // non-existing + "org.webjars" % "npm" % "0.0.99" +) +updateConfiguration := updateConfiguration.value.withMissingOk(true) + +lazy val check = taskKey[Unit]("") + +check := { + val updateReport = update.value + val updateClassifiersReport = updateClassifiers.value + + val compileReport = updateReport + .configuration(Compile) + .getOrElse { + sys.error("Compile configuration not found in update report") + } + + val compileClassifiersReport = updateClassifiersReport + .configuration(Compile) + .getOrElse { + sys.error("Compile configuration not found in update classifiers report") + } + + val shapelessModule = compileReport + .modules + .find(_.module.name == "shapeless_2.13") + .getOrElse { + sys.error(s"shapeless module not found in ${compileReport.modules.map(_.module)}") + } + + val shapelessClassifiersModule = compileClassifiersReport + .modules + .find(_.module.name == "shapeless_2.13") + .getOrElse { + sys.error(s"shapeless module not found in ${compileClassifiersReport.modules.map(_.module)}") + } +} diff --git a/modules/sbt-coursier/src/sbt-test/shared-2/missingok/project/plugins.sbt b/modules/sbt-coursier/src/sbt-test/shared-2/missingok/project/plugins.sbt new file mode 100644 index 000000000..503ac2871 --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-2/missingok/project/plugins.sbt @@ -0,0 +1,13 @@ +addSbtPlugin { + + val name = sys.props.getOrElse( + "plugin.name", + sys.error("plugin.name Java property not set") + ) + val version = sys.props.getOrElse( + "plugin.version", + sys.error("plugin.version Java property not set") + ) + + "io.get-coursier" % name % version +} diff --git a/modules/sbt-coursier/src/sbt-test/shared-2/missingok/test b/modules/sbt-coursier/src/sbt-test/shared-2/missingok/test new file mode 100644 index 000000000..15675b169 --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/shared-2/missingok/test @@ -0,0 +1 @@ +> check diff --git a/modules/sbt-lm-coursier/src/main/scala/coursier/sbtlmcoursier/LmCoursierPlugin.scala b/modules/sbt-lm-coursier/src/main/scala/coursier/sbtlmcoursier/LmCoursierPlugin.scala index b6bac8e3e..b687e6627 100644 --- a/modules/sbt-lm-coursier/src/main/scala/coursier/sbtlmcoursier/LmCoursierPlugin.scala +++ b/modules/sbt-lm-coursier/src/main/scala/coursier/sbtlmcoursier/LmCoursierPlugin.scala @@ -7,7 +7,7 @@ import coursier.sbtcoursiershared.{InputsTasks, SbtCoursierShared} import sbt.{AutoPlugin, Classpaths, Def, Setting, Task, taskKey} import sbt.Project.inTask import sbt.KeyRanks.DTask -import sbt.Keys.{appConfiguration, autoScalaLibrary, classpathTypes, dependencyOverrides, dependencyResolution, ivyPaths, scalaBinaryVersion, scalaModuleInfo, scalaOrganization, scalaVersion, streams, updateClassifiers, updateSbtClassifiers} +import sbt.Keys.{appConfiguration, autoScalaLibrary, classpathTypes, dependencyOverrides, dependencyResolution, ivyPaths, scalaBinaryVersion, scalaModuleInfo, scalaOrganization, scalaVersion, streams, updateClassifiers, updateConfiguration, updateSbtClassifiers} import sbt.librarymanagement.DependencyResolution import scala.language.reflectiveCalls @@ -125,6 +125,7 @@ object LmCoursierPlugin extends AutoPlugin { val sbtScalaVersion = internalSbtScalaProvider.version() val sbtScalaOrganization = "org.scala-lang" // always assuming sbt uses mainline scala val classifiers = classifiersTask.value + val updateConfig = updateConfiguration.value val s = streams.value Classpaths.warnResolversConflict(rs, s.log) CoursierConfiguration() @@ -159,6 +160,7 @@ object LmCoursierPlugin extends AutoPlugin { .withIvyHome(ivyPaths.value.ivyHome) .withStrict(strict) .withForceVersions(userForceVersions.toVector) + .withMissingOk(updateConfig.missingOk) } } private def mkDependencyResolution: Def.Initialize[Task[DependencyResolution]] =