diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index d103829ae..2bc1c71ff 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -2364,6 +2364,7 @@ object Classpaths { ), ivySbt := ivySbt0.value, ivyModule := { val is = ivySbt.value; new is.Module(moduleSettings.value) }, + allCredentials := LMCoursier.allCredentialsTask.value, transitiveUpdate := transitiveUpdateTask.value, updateCacheName := { val binVersion = scalaBinaryVersion.value diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index b50013d8c..242b75579 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -376,6 +376,7 @@ object Keys { val packagedArtifacts = taskKey[Map[Artifact, File]]("Packages all artifacts for publishing and maps the Artifact definition to the generated file.").withRank(CTask) val publishMavenStyle = settingKey[Boolean]("Configures whether to generate and publish a pom (true) or Ivy file (false).").withRank(BSetting) val credentials = taskKey[Seq[Credentials]]("The credentials to use for updating and publishing.").withRank(BMinusTask) + val allCredentials = taskKey[Seq[Credentials]]("Aggregated credentials across current and root subprojects. Do not rewire this task.").withRank(DTask) val makePom = taskKey[File]("Generates a pom for publishing when publishing Maven-style.").withRank(BPlusTask) val deliver = taskKey[File]("Generates the Ivy file for publishing to a repository.").withRank(BTask) diff --git a/main/src/main/scala/sbt/coursierint/CoursierInputsTasks.scala b/main/src/main/scala/sbt/coursierint/CoursierInputsTasks.scala index 4836e1335..655eff843 100644 --- a/main/src/main/scala/sbt/coursierint/CoursierInputsTasks.scala +++ b/main/src/main/scala/sbt/coursierint/CoursierInputsTasks.scala @@ -204,7 +204,7 @@ object CoursierInputsTasks { val credentialsTask = Def.task { val log = streams.value.log - val creds = sbt.Keys.credentials.value + val creds = sbt.Keys.allCredentials.value .flatMap { case dc: IvyDirectCredentials => List(dc) case fc: FileCredentials => diff --git a/main/src/main/scala/sbt/coursierint/LMCoursier.scala b/main/src/main/scala/sbt/coursierint/LMCoursier.scala index f84a19afa..11c9badb3 100644 --- a/main/src/main/scala/sbt/coursierint/LMCoursier.scala +++ b/main/src/main/scala/sbt/coursierint/LMCoursier.scala @@ -9,6 +9,7 @@ package sbt package coursierint import java.io.File +import java.util.concurrent.ConcurrentHashMap import lmcoursier.definitions.{ Classifier, Configuration => CConfiguration, @@ -19,11 +20,15 @@ import lmcoursier._ import lmcoursier.credentials.Credentials import Keys._ import sbt.librarymanagement._ +import sbt.librarymanagement.ivy.{ Credentials => IvyCredentials } import sbt.util.Logger import sbt.io.syntax._ import xsbti.AppConfiguration object LMCoursier { + private[this] val credentialRegistry: ConcurrentHashMap[(String, String), IvyCredentials] = + new ConcurrentHashMap + def defaultCacheLocation: File = sys.props.get("sbt.coursier.home") match { case Some(home) => new File(home).getAbsoluteFile / "cache" @@ -188,4 +193,19 @@ object LMCoursier { def publicationsSetting(packageConfigs: Seq[(Configuration, CConfiguration)]): Def.Setting[_] = { csrPublications := CoursierArtifactsTasks.coursierPublicationsTask(packageConfigs: _*).value } + + private[sbt] def registerCredentials(creds: IvyCredentials): Unit = { + val d = IvyCredentials.toDirect(creds) + credentialRegistry.put((d.host, d.realm), d) + () + } + + // This emulates Ivy's credential registration which basically keeps mutating global registry + def allCredentialsTask: Def.Initialize[Task[Seq[IvyCredentials]]] = Def.task { + import scala.collection.JavaConverters._ + (Keys.credentials in ThisBuild).value foreach registerCredentials + (Keys.credentials in LocalRootProject).value foreach registerCredentials + Keys.credentials.value foreach registerCredentials + credentialRegistry.values.asScala.toVector + } }