From 364ba9b44b676012ab655c3dae9d894a16bd6a84 Mon Sep 17 00:00:00 2001 From: Alexey Alekhin Date: Sat, 23 Sep 2017 15:20:43 +0200 Subject: [PATCH 1/8] Removed extra slash in the localBasePattern When the `scala_[scalaVersion]/` segment is present and the `/[branch]` segment isn't, an extra slash appears before `/[revision]`. --- core/src/main/scala/sbt/librarymanagement/ResolverExtra.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/scala/sbt/librarymanagement/ResolverExtra.scala b/core/src/main/scala/sbt/librarymanagement/ResolverExtra.scala index b49b934b5..c8c3064f7 100644 --- a/core/src/main/scala/sbt/librarymanagement/ResolverExtra.scala +++ b/core/src/main/scala/sbt/librarymanagement/ResolverExtra.scala @@ -357,7 +357,7 @@ abstract class ResolverFunctions { def mavenStyleBasePattern = "[organisation]/[module](_[scalaVersion])(_[sbtVersion])/[revision]/[artifact]-[revision](-[classifier]).[ext]" def localBasePattern = - "[organisation]/[module]/" + PluginPattern + "(/[branch])/[revision]/[type]s/[artifact](-[classifier]).[ext]" + "[organisation]/[module]/" + PluginPattern + "([branch]/)[revision]/[type]s/[artifact](-[classifier]).[ext]" def defaultRetrievePattern = "[type]s/[organisation]/[module]/" + PluginPattern + "[artifact](-[revision])(-[classifier]).[ext]" final val PluginPattern = "(scala_[scalaVersion]/)(sbt_[sbtVersion]/)" From 08fedf787b490c736cc32025fd86ccbae732b33e Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 26 Sep 2017 10:43:34 +0200 Subject: [PATCH 2/8] Add file name to exception message --- .../scala/sbt/internal/librarymanagement/ConvertResolver.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ivy/src/main/scala/sbt/internal/librarymanagement/ConvertResolver.scala b/ivy/src/main/scala/sbt/internal/librarymanagement/ConvertResolver.scala index 30b8c8b1b..fb84d2468 100644 --- a/ivy/src/main/scala/sbt/internal/librarymanagement/ConvertResolver.scala +++ b/ivy/src/main/scala/sbt/internal/librarymanagement/ConvertResolver.scala @@ -367,7 +367,7 @@ private[sbt] object ConvertResolver { // Here we duplicate the put method for files so we don't just bail on trying ot use Http handler val resource = getResource(destination) if (!overwrite && resource.exists()) { - throw new IOException("destination file exists and overwrite == false"); + throw new IOException(s"Destination file $destination exists and overwrite == false"); } fireTransferInitiated(resource, TransferEvent.REQUEST_PUT); try { From fd0d53851124bd0afeb1ccdcc48c6822b5e3f769 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 13 Oct 2017 14:08:17 +0100 Subject: [PATCH 3/8] On JDK 9 call java.net.Authenticator.getDefault JDK 9 complains when java.lang.reflect.Field#setAccessible is called. So on JDK 9 to get the default Authenticator on JDK you can just call Authenticator.getDefault(). However lm targets JDK 8.. So on JDK 8 we do what we've always done, and on JDK 9 we use java reflection to call Authenticator.getDefault(), which is public and doesn't require setAccessible(true). Fixes #169 --- .../ivyint/ErrorMessageAuthenticator.scala | 45 ++++++++++++++++--- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/ErrorMessageAuthenticator.scala b/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/ErrorMessageAuthenticator.scala index 78e1154dc..1e842c458 100644 --- a/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/ErrorMessageAuthenticator.scala +++ b/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/ErrorMessageAuthenticator.scala @@ -1,6 +1,7 @@ package sbt.internal.librarymanagement package ivyint +import java.lang.reflect.InvocationTargetException import java.net.{ Authenticator, PasswordAuthentication } import org.apache.ivy.util.Message @@ -14,18 +15,41 @@ object ErrorMessageAuthenticator { private var securityWarningLogged = false private def originalAuthenticator: Option[Authenticator] = { - try { + if (isJavaVersion9Plus) getDefaultAuthenticator else getTheAuthenticator + } + + private[this] def getTheAuthenticator: Option[Authenticator] = { + withJavaReflectErrorHandling { val field = classOf[Authenticator].getDeclaredField("theAuthenticator") field.setAccessible(true) Option(field.get(null).asInstanceOf[Authenticator]) - } catch { - // TODO - Catch more specific errors. - case t: Throwable => - Message.debug("Error occurred while getting the original authenticator: " + t.getMessage) - None } } + private[this] def getDefaultAuthenticator: Option[Authenticator] = + withJavaReflectErrorHandling { + val method = classOf[Authenticator].getDeclaredMethod("getDefault") + Option(method.invoke(null).asInstanceOf[Authenticator]) + } + + private[this] def withJavaReflectErrorHandling[A](t: => Option[A]): Option[A] = { + try t + catch { + case e: ReflectiveOperationException => handleReflectionException(e) + case e: SecurityException => handleReflectionException(e) + case e: InvocationTargetException => handleReflectionException(e) + case e: ExceptionInInitializerError => handleReflectionException(e) + case e: IllegalArgumentException => handleReflectionException(e) + case e: NullPointerException => handleReflectionException(e) + case e: ClassCastException => handleReflectionException(e) + } + } + + private[this] def handleReflectionException(t: Throwable) = { + Message.debug("Error occurred while getting the original authenticator: " + t.getMessage) + None + } + private lazy val ivyOriginalField = { val field = classOf[IvyAuthenticator].getDeclaredField("original") field.setAccessible(true) @@ -76,6 +100,15 @@ object ErrorMessageAuthenticator { } doInstallIfIvy(originalAuthenticator) } + + private[this] def isJavaVersion9Plus = javaVersion > 8 + private[this] def javaVersion = { + // See Oracle section 1.5.3 at: + // https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html + val version = sys.props("java.specification.version").split("\\.").map(_.toInt) + if (version(0) == 1) version(1) else version(0) + } + } /** From dcdbcd4979e97115d018928a0b9666c7e5d35ce8 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 24 Oct 2017 03:15:49 -0400 Subject: [PATCH 4/8] Bump Ivy to 2.3.0-sbt-1b57d3bbc08ecf671169fd548918da18c91f77be Ref https://github.com/sbt/ivy/pull/26 Ref sbt/launcher#38 JDK 9 complains when java.lang.reflect.Field#setAccessible is called. So on JDK 9 to get the default Authenticator on JDK you can just call Authenticator.getDefault(). However ivy targets JDK 6.. So on JDK < 9 we do what we've always done, and on JDK 9+ we use java reflection to call Authenticator.getDefault(), which is public and doesn't require setAccessible(true). --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index fae131ba4..b4b7d372e 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -40,7 +40,7 @@ object Dependencies { def addSbtUtilCache(p: Project): Project = addSbtModule(p, sbtUtilPath, "utilCache", utilCache) val launcherInterface = "org.scala-sbt" % "launcher-interface" % "1.0.0" - val ivy = "org.scala-sbt.ivy" % "ivy" % "2.3.0-sbt-a3314352b638afbf0dca19f127e8263ed6f898bd" + val ivy = "org.scala-sbt.ivy" % "ivy" % "2.3.0-sbt-1b57d3bbc08ecf671169fd548918da18c91f77be" val jsch = "com.jcraft" % "jsch" % "0.1.46" intransitive () val scalaReflect = Def.setting { "org.scala-lang" % "scala-reflect" % scalaVersion.value } val scalaCompiler = Def.setting { "org.scala-lang" % "scala-compiler" % scalaVersion.value } From f4241c4d6524846e0a1e0c1078f6ba106189dc17 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 15 Nov 2017 15:58:29 +0000 Subject: [PATCH 5/8] Bump to latest Ivy Includes sbt/ivy#27 which fixes a JDK 9 issue. Similar to PR sbt/launcher#46. --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index b4b7d372e..2c38cb532 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -40,7 +40,7 @@ object Dependencies { def addSbtUtilCache(p: Project): Project = addSbtModule(p, sbtUtilPath, "utilCache", utilCache) val launcherInterface = "org.scala-sbt" % "launcher-interface" % "1.0.0" - val ivy = "org.scala-sbt.ivy" % "ivy" % "2.3.0-sbt-1b57d3bbc08ecf671169fd548918da18c91f77be" + val ivy = "org.scala-sbt.ivy" % "ivy" % "2.3.0-sbt-b18f59ea3bc914a297bb6f1a4f7fb0ace399e310" val jsch = "com.jcraft" % "jsch" % "0.1.46" intransitive () val scalaReflect = Def.setting { "org.scala-lang" % "scala-reflect" % scalaVersion.value } val scalaCompiler = Def.setting { "org.scala-lang" % "scala-compiler" % scalaVersion.value } From 8330d164316540b4b6aba89b5833a0c96a9035e9 Mon Sep 17 00:00:00 2001 From: Tim Underwood Date: Wed, 22 Nov 2017 10:48:59 -0800 Subject: [PATCH 6/8] Be friendly to SBT plugins that also use URLHandlerRegistry.setDefault Other plugins (for example: https://github.com/frugalmechanic/fm-sbt-s3-resolver) also make use of the URLHandlerRegistry.setDefault mechanism to register handlers for other protocols (e.g. "s3"). This change makes it so that SBT will only register the http/https protocols and will preserve any other protocol handlers that have already been registered. --- .../sbt/internal/librarymanagement/Ivy.scala | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala b/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala index c2b5b6cfb..95c4d3db2 100644 --- a/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala +++ b/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala @@ -80,16 +80,29 @@ final class IvySbt(val configuration: IvyConfiguration) { self => } private lazy val basicUrlHandler: URLHandler = new BasicURLHandler - private lazy val gigahorseUrlHandler: URLHandler = { - val dispatcher = new URLHandlerDispatcher - val handler = new GigahorseUrlHandler - dispatcher.setDownloader("http", handler) - dispatcher.setDownloader("https", handler) - dispatcher - } + private lazy val gigahorseUrlHandler: URLHandler = new GigahorseUrlHandler + private lazy val settings: IvySettings = { - if (configuration.updateOptions.gigahorse) URLHandlerRegistry.setDefault(gigahorseUrlHandler) - else URLHandlerRegistry.setDefault(basicUrlHandler) + val dispatcher: URLHandlerDispatcher = URLHandlerRegistry.getDefault match { + // If the default is already a URLHandlerDispatcher then just use that + case disp: URLHandlerDispatcher => disp + + // Otherwise wrap the existing URLHandler in a URLHandlerDispatcher + // while retaining the existing URLHandler as the default. + case default => + val disp: URLHandlerDispatcher = new URLHandlerDispatcher() + disp.setDefault(default) + URLHandlerRegistry.setDefault(disp) + disp + } + + val urlHandler: URLHandler = if (configuration.updateOptions.gigahorse) gigahorseUrlHandler else basicUrlHandler + + // Only set the urlHandler for the http/https protocols so we do not conflict with any other plugins + // that might register other protocol handlers. + // For example https://github.com/frugalmechanic/fm-sbt-s3-resolver registers "s3" + dispatcher.setDownloader("http", urlHandler) + dispatcher.setDownloader("https", urlHandler) val is = new IvySettings is.setCircularDependencyStrategy( From 7f3954d8bbb62f28af86530e64ee439aa55b84bb Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 24 Nov 2017 17:14:46 -0500 Subject: [PATCH 7/8] Bump IO and Util --- project/Dependencies.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index b4b7d372e..62c33378c 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -3,11 +3,11 @@ import Keys._ import sbt.contraband.ContrabandPlugin.autoImport._ object Dependencies { - val scala211 = "2.11.11" - val scala212 = "2.12.3" + val scala211 = "2.11.12" + val scala212 = "2.12.4" - private val ioVersion = "1.0.0" - private val utilVersion = "1.0.0" + private val ioVersion = "1.0.2" + private val utilVersion = "1.0.3" private val sbtIO = "org.scala-sbt" %% "io" % ioVersion From df177ff56eedbf674c4fe00f7567fcd9950a07d9 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 24 Nov 2017 20:16:36 -0500 Subject: [PATCH 8/8] Formatting --- ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala b/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala index 95c4d3db2..cdbfd2ee3 100644 --- a/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala +++ b/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala @@ -96,7 +96,8 @@ final class IvySbt(val configuration: IvyConfiguration) { self => disp } - val urlHandler: URLHandler = if (configuration.updateOptions.gigahorse) gigahorseUrlHandler else basicUrlHandler + val urlHandler: URLHandler = + if (configuration.updateOptions.gigahorse) gigahorseUrlHandler else basicUrlHandler // Only set the urlHandler for the http/https protocols so we do not conflict with any other plugins // that might register other protocol handlers.