diff --git a/plugin/src/main/scala-2.10/coursier/CoursierPlugin.scala b/plugin/src/main/scala-2.10/coursier/CoursierPlugin.scala index ce49d012c..04c5979e5 100644 --- a/plugin/src/main/scala-2.10/coursier/CoursierPlugin.scala +++ b/plugin/src/main/scala-2.10/coursier/CoursierPlugin.scala @@ -19,6 +19,7 @@ object CoursierPlugin extends AutoPlugin { val coursierSourceRepositories = Keys.coursierSourceRepositories val coursierResolvers = Keys.coursierResolvers val coursierSbtResolvers = Keys.coursierSbtResolvers + val coursierCredentials = Keys.coursierCredentials val coursierFallbackDependencies = Keys.coursierFallbackDependencies val coursierCache = Keys.coursierCache val coursierProject = Keys.coursierProject @@ -61,6 +62,7 @@ object CoursierPlugin extends AutoPlugin { coursierSourceRepositories := Nil, coursierResolvers <<= Tasks.coursierResolversTask, coursierSbtResolvers <<= externalResolvers in updateSbtClassifiers, + coursierCredentials := Map.empty, coursierFallbackDependencies <<= Tasks.coursierFallbackDependenciesTask, coursierCache := Cache.default, update <<= Tasks.updateTask(withClassifiers = false), diff --git a/plugin/src/main/scala-2.10/coursier/Credentials.scala b/plugin/src/main/scala-2.10/coursier/Credentials.scala new file mode 100644 index 000000000..c3229fe17 --- /dev/null +++ b/plugin/src/main/scala-2.10/coursier/Credentials.scala @@ -0,0 +1,57 @@ +package coursier + +import java.io.{File, FileInputStream} +import java.util.Properties + +import coursier.core.Authentication + +sealed abstract class Credentials extends Product with Serializable { + def user: String + def password: String + + def authentication: Authentication = + Authentication(user, password) +} + +object Credentials { + + case class Direct(user: String, password: String) extends Credentials { + override def toString = s"Direct($user, ******)" + } + + case class FromFile(file: File) extends Credentials { + + private lazy val props = { + val p = new Properties() + p.load(new FileInputStream(file)) + p + } + + private def findKey(keys: Seq[String]) = keys + .iterator + .map(props.getProperty) + .filter(_ != null) + .toStream + .headOption + .getOrElse { + throw new NoSuchElementException(s"${keys.head} key in $file") + } + + lazy val user: String = findKey(FromFile.fileUserKeys) + lazy val password: String = findKey(FromFile.filePasswordKeys) + } + + object FromFile { + // from sbt.Credentials + private val fileUserKeys = Seq("user", "user.name", "username") + private val filePasswordKeys = Seq("password", "pwd", "pass", "passwd") + } + + + def apply(user: String, password: String): Credentials = + Direct(user, password) + + def apply(file: File): Credentials = + FromFile(file) + +} diff --git a/plugin/src/main/scala-2.10/coursier/FromSbt.scala b/plugin/src/main/scala-2.10/coursier/FromSbt.scala index be68cc9fb..28ac928da 100644 --- a/plugin/src/main/scala-2.10/coursier/FromSbt.scala +++ b/plugin/src/main/scala-2.10/coursier/FromSbt.scala @@ -4,6 +4,7 @@ import coursier.ivy.{ IvyXml, IvyRepository } import java.net.{ MalformedURLException, URL } +import coursier.core.Authentication import sbt.{ Resolver, CrossVersion, ModuleID } import sbt.mavenint.SbtPomExtraProperties @@ -145,11 +146,21 @@ object FromSbt { } else None - private def mavenRepositoryOpt(root: String, log: sbt.Logger): Option[MavenRepository] = + private def mavenRepositoryOpt( + root: String, + log: sbt.Logger, + authentication: Option[Authentication] + ): Option[MavenRepository] = try { Cache.url(root) // ensure root is a URL whose protocol can be handled here val root0 = if (root.endsWith("/")) root else root + "/" - Some(MavenRepository(root0, sbtAttrStub = true)) + Some( + MavenRepository( + root0, + sbtAttrStub = true, + authentication = authentication + ) + ) } catch { case e: MalformedURLException => log.warn( @@ -165,11 +176,12 @@ object FromSbt { def repository( resolver: Resolver, ivyProperties: Map[String, String], - log: sbt.Logger + log: sbt.Logger, + authentication: Option[Authentication] ): Option[Repository] = resolver match { case sbt.MavenRepository(_, root) => - mavenRepositoryOpt(root, log) + mavenRepositoryOpt(root, log, authentication) case sbt.FileRepository(_, _, patterns) if patterns.ivyPatterns.lengthCompare(1) == 0 && @@ -184,10 +196,11 @@ object FromSbt { metadataPatternOpt = Some("file://" + patterns.ivyPatterns.head), changing = Some(true), properties = ivyProperties, - dropInfoAttributes = true + dropInfoAttributes = true, + authentication = authentication )) case Some(mavenCompatibleBase) => - mavenRepositoryOpt("file://" + mavenCompatibleBase, log) + mavenRepositoryOpt("file://" + mavenCompatibleBase, log, authentication) } case sbt.URLRepository(_, patterns) @@ -203,10 +216,11 @@ object FromSbt { metadataPatternOpt = Some(patterns.ivyPatterns.head), changing = None, properties = ivyProperties, - dropInfoAttributes = true + dropInfoAttributes = true, + authentication = authentication )) case Some(mavenCompatibleBase) => - mavenRepositoryOpt(mavenCompatibleBase, log) + mavenRepositoryOpt(mavenCompatibleBase, log, authentication) } case other => diff --git a/plugin/src/main/scala-2.10/coursier/Keys.scala b/plugin/src/main/scala-2.10/coursier/Keys.scala index 47de5297c..995f74084 100644 --- a/plugin/src/main/scala-2.10/coursier/Keys.scala +++ b/plugin/src/main/scala-2.10/coursier/Keys.scala @@ -18,6 +18,7 @@ object Keys { val coursierSourceRepositories = SettingKey[Seq[File]]("coursier-source-repositories") val coursierResolvers = TaskKey[Seq[Resolver]]("coursier-resolvers") val coursierSbtResolvers = TaskKey[Seq[Resolver]]("coursier-sbt-resolvers") + val coursierCredentials = TaskKey[Map[String, Credentials]]("coursier-credentials") val coursierCache = SettingKey[File]("coursier-cache") diff --git a/plugin/src/main/scala-2.10/coursier/Tasks.scala b/plugin/src/main/scala-2.10/coursier/Tasks.scala index 65e997e62..e8fe7551f 100644 --- a/plugin/src/main/scala-2.10/coursier/Tasks.scala +++ b/plugin/src/main/scala-2.10/coursier/Tasks.scala @@ -371,6 +371,8 @@ object Tasks { "ivy.home" -> (new File(sys.props("user.home")).toURI.getPath + ".ivy2") ) ++ sys.props + val credentials = coursierCredentials.value + val sourceRepositories0 = sourceRepositories.map { base => MavenRepository(base.toURI.toString, changing = Some(true)) @@ -393,7 +395,14 @@ object Tasks { val repositories = Seq(globalPluginsRepo, interProjectRepo) ++ sourceRepositories0 ++ - resolvers.flatMap(FromSbt.repository(_, ivyProperties, log)) ++ + resolvers.flatMap { resolver => + FromSbt.repository( + resolver, + ivyProperties, + log, + credentials.get(resolver.name).map(_.authentication) + ) + } ++ fallbackDependenciesRepositories def resolution = { diff --git a/plugin/src/sbt-test/sbt-coursier/credentials-from-file/build.sbt b/plugin/src/sbt-test/sbt-coursier/credentials-from-file/build.sbt new file mode 100644 index 000000000..1e51c1a90 --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/credentials-from-file/build.sbt @@ -0,0 +1,9 @@ +scalaVersion := "2.11.8" + +resolvers += "authenticated" at "http://localhost:8080" + +coursierCredentials += "authenticated" -> coursier.Credentials(file("credentials")) + +coursierCachePolicies := Seq(coursier.CachePolicy.ForceDownload) + +libraryDependencies += "com.abc" % "test" % "0.1" diff --git a/plugin/src/sbt-test/sbt-coursier/credentials-from-file/credentials b/plugin/src/sbt-test/sbt-coursier/credentials-from-file/credentials new file mode 100644 index 000000000..03c71b2e5 --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/credentials-from-file/credentials @@ -0,0 +1,2 @@ +user=user +password=pass diff --git a/plugin/src/sbt-test/sbt-coursier/credentials-from-file/project/plugins.sbt b/plugin/src/sbt-test/sbt-coursier/credentials-from-file/project/plugins.sbt new file mode 100644 index 000000000..152225a9e --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/credentials-from-file/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/credentials-from-file/src/main/scala/Main.scala b/plugin/src/sbt-test/sbt-coursier/credentials-from-file/src/main/scala/Main.scala new file mode 100644 index 000000000..86ae9e9e3 --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/credentials-from-file/src/main/scala/Main.scala @@ -0,0 +1 @@ +object Main extends App \ No newline at end of file diff --git a/plugin/src/sbt-test/sbt-coursier/credentials-from-file/test b/plugin/src/sbt-test/sbt-coursier/credentials-from-file/test new file mode 100644 index 000000000..4d96ce4c9 --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/credentials-from-file/test @@ -0,0 +1 @@ +> coursierResolution diff --git a/plugin/src/sbt-test/sbt-coursier/credentials/build.sbt b/plugin/src/sbt-test/sbt-coursier/credentials/build.sbt new file mode 100644 index 000000000..619f464cd --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/credentials/build.sbt @@ -0,0 +1,9 @@ +scalaVersion := "2.11.8" + +resolvers += "authenticated" at "http://localhost:8080" + +coursierCredentials += "authenticated" -> coursier.Credentials("user", "pass") + +coursierCachePolicies := Seq(coursier.CachePolicy.ForceDownload) + +libraryDependencies += "com.abc" % "test" % "0.1" \ No newline at end of file diff --git a/plugin/src/sbt-test/sbt-coursier/credentials/project/plugins.sbt b/plugin/src/sbt-test/sbt-coursier/credentials/project/plugins.sbt new file mode 100644 index 000000000..152225a9e --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/credentials/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/credentials/src/main/scala/Main.scala b/plugin/src/sbt-test/sbt-coursier/credentials/src/main/scala/Main.scala new file mode 100644 index 000000000..86ae9e9e3 --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/credentials/src/main/scala/Main.scala @@ -0,0 +1 @@ +object Main extends App \ No newline at end of file diff --git a/plugin/src/sbt-test/sbt-coursier/credentials/test b/plugin/src/sbt-test/sbt-coursier/credentials/test new file mode 100644 index 000000000..4d96ce4c9 --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/credentials/test @@ -0,0 +1 @@ +> coursierResolution