diff --git a/build.sbt b/build.sbt index 5c9672d8d..591b02d1f 100644 --- a/build.sbt +++ b/build.sbt @@ -2,7 +2,12 @@ import Dependencies._ import Path._ import com.typesafe.tools.mima.core._, ProblemFilters._ -def commonSettings: Seq[Setting[_]] = Def settings ( +val _ = { + //https://github.com/sbt/contraband/issues/122 + sys.props += ("line.separator" -> "\n") +} + +def commonSettings: Seq[Setting[_]] = Def.settings( scalaVersion := scala212, // publishArtifact in packageDoc := false, resolvers += Resolver.typesafeIvyRepo("releases"), @@ -31,7 +36,7 @@ def commonSettings: Seq[Setting[_]] = Def settings ( val mimaSettings = Def settings ( mimaPreviousArtifacts := Set( "1.0.0", "1.0.1", "1.0.2", "1.0.3", "1.0.4", - "1.1.0", "1.1.1", "1.1.2", "1.1.3", + "1.1.0", "1.1.1", "1.1.2", "1.1.3", "1.1.4", ) map (version => organization.value %% moduleName.value % version cross (if (crossPaths.value) CrossVersion.binary else CrossVersion.disabled) @@ -54,7 +59,7 @@ lazy val lmRoot = (project in file(".")) git.baseVersion := "1.2.0", version := { val v = version.value - if (v contains "SNAPSHOT") git.baseVersion.value + if (v contains "SNAPSHOT") git.baseVersion.value + "-SNAPSHOT" else v } )), @@ -215,7 +220,7 @@ lazy val lmIvy = (project in file("ivy")) .settings( commonSettings, name := "librarymanagement-ivy", - libraryDependencies ++= Seq(ivy, scalaTest % Test, scalaCheck % Test), + libraryDependencies ++= Seq(ivy), managedSourceDirectories in Compile += baseDirectory.value / "src" / "main" / "contraband-scala", sourceManaged in (Compile, generateContrabands) := baseDirectory.value / "src" / "main" / "contraband-scala", diff --git a/core/src/main/scala/sbt/librarymanagement/Http.scala b/core/src/main/scala/sbt/librarymanagement/Http.scala index 9870d9b0f..833a9edc0 100644 --- a/core/src/main/scala/sbt/librarymanagement/Http.scala +++ b/core/src/main/scala/sbt/librarymanagement/Http.scala @@ -3,5 +3,5 @@ package sbt.librarymanagement import gigahorse._, support.okhttp.Gigahorse object Http { - lazy val http: HttpClient = Gigahorse.http(Gigahorse.config) + lazy val http: HttpClient = Gigahorse.http(gigahorse.Config()) } diff --git a/ivy/src/main/scala/sbt/internal/librarymanagement/ConvertResolver.scala b/ivy/src/main/scala/sbt/internal/librarymanagement/ConvertResolver.scala index 0cc3bbbe1..47d597660 100644 --- a/ivy/src/main/scala/sbt/internal/librarymanagement/ConvertResolver.scala +++ b/ivy/src/main/scala/sbt/internal/librarymanagement/ConvertResolver.scala @@ -7,7 +7,7 @@ import java.net.URL import java.util.Collections import org.apache.ivy.core.module.descriptor.DependencyDescriptor -import org.apache.ivy.core.resolve.ResolveData +import org.apache.ivy.core.resolve.{ DownloadOptions, ResolveData } import org.apache.ivy.core.settings.IvySettings import org.apache.ivy.plugins.repository.{ RepositoryCopyProgressListener, Resource, TransferEvent } import org.apache.ivy.plugins.resolver.{ @@ -30,6 +30,7 @@ import java.io.{ File, IOException } import org.apache.ivy.util.{ ChecksumHelper, FileUtil, Message } import org.apache.ivy.core.module.descriptor.{ Artifact => IArtifact } +import org.apache.ivy.core.report.DownloadReport import sbt.io.IO import sbt.util.Logger import sbt.librarymanagement._ @@ -181,7 +182,7 @@ private[sbt] object ConvertResolver { resolver } case repo: SshRepository => { - val resolver = new SshResolver with DescriptorRequired { + val resolver = new SshResolver with DescriptorRequired with ThreadSafeSshBasedResolver { override val managedChecksumsEnabled: Boolean = managedChecksums override def getResource(resource: Resource, dest: File): Long = get(resource, dest) } @@ -190,7 +191,7 @@ private[sbt] object ConvertResolver { resolver } case repo: SftpRepository => { - val resolver = new SFTPResolver + val resolver = new SFTPResolver with ThreadSafeSshBasedResolver initializeSSHResolver(resolver, repo, settings) resolver } @@ -405,4 +406,15 @@ private[sbt] object ConvertResolver { } } } + + private sealed trait ThreadSafeSshBasedResolver + extends org.apache.ivy.plugins.resolver.AbstractSshBasedResolver { +//uncomment to test non-threadsafe behavior +// private def lock = new Object + private val lock = org.apache.ivy.plugins.repository.ssh.SshCache.getInstance + override def download(artifacts: Array[IArtifact], options: DownloadOptions): DownloadReport = + lock.synchronized { + super.download(artifacts, options) + } + } } diff --git a/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/GigahorseUrlHandler.scala b/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/GigahorseUrlHandler.scala index fd11a35fe..4c80cd152 100644 --- a/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/GigahorseUrlHandler.scala +++ b/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/GigahorseUrlHandler.scala @@ -214,7 +214,7 @@ object GigahorseUrlHandler { private val EmptyBuffer: Array[Byte] = new Array[Byte](0) - lazy val http: HttpClient = Gigahorse.http(Gigahorse.config) + lazy val http: HttpClient = Gigahorse.http(gigahorse.Config()) private lazy val okHttpClient: OkHttpClient = { http diff --git a/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/SbtChainResolver.scala b/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/SbtChainResolver.scala index d16ec40e3..3e70ecafc 100644 --- a/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/SbtChainResolver.scala +++ b/ivy/src/main/scala/sbt/internal/librarymanagement/ivyint/SbtChainResolver.scala @@ -85,8 +85,8 @@ private[sbt] case class SbtChainResolver( dd: DependencyDescriptor, data: ResolveData ): ResolvedModuleRevision = { - if (data.getOptions.getLog != LogOptions.LOG_QUIET) - Message.debug("Resolving " + dd.getDependencyRevisionId + " ...") + if (data.getOptions.getLog == LogOptions.LOG_DEFAULT) + Message.info("Resolving " + dd.getDependencyRevisionId + " ...") val gd = CustomSbtResolution.getDependency(dd, data) val mod = IvySbt.resetArtifactResolver(gd) mod diff --git a/ivy/src/test/scala/sbt/internal/librarymanagement/SftpRepoSpec.scala b/ivy/src/test/scala/sbt/internal/librarymanagement/SftpRepoSpec.scala new file mode 100644 index 000000000..8da14644a --- /dev/null +++ b/ivy/src/test/scala/sbt/internal/librarymanagement/SftpRepoSpec.scala @@ -0,0 +1,42 @@ +package sbt.internal.librarymanagement + +import sbt.io._ +import sbt.io.syntax._ +import sbt.util.Level +import sbt.librarymanagement._ +import sbt.librarymanagement.syntax._ +import java.nio.file.Paths + +//by default this test is ignored +//to run this you need to change "repo" to point to some sftp repository which contains a dependency referring a dependency in same repo +//it will then attempt to authenticate via key file and fetch the dependency specified via "org" and "module" +class SftpRepoSpec extends BaseIvySpecification { + val repo: Option[String] = None +// val repo: Option[String] = Some("some repo") + //a dependency which depends on another in the repo + def org(repo: String) = s"com.${repo}" + def module(org: String) = org % "some-lib" % "version" + + override def resolvers = { + implicit val patterns = Resolver.defaultIvyPatterns + repo.map { repo => + val privateKeyFile = Paths.get(sys.env("HOME"), ".ssh", s"id_${repo}").toFile + Resolver.sftp(repo, s"repo.${repo}.com", 2222).as(repo, privateKeyFile) + }.toVector ++ super.resolvers + } + + "resolving multiple deps from sftp repo" should "not hang or fail" in { + repo match { + case Some(repo) => + IO.delete(currentTarget / "cache" / org(repo)) + // log.setLevel(Level.Debug) + lmEngine().retrieve(module(org(repo)), scalaModuleInfo = None, currentTarget, log) match { + case Right(v) => log.debug(v.toString()) + case Left(e) => + log.log(Level.Error, e.failedPaths.toString()) + throw e.resolveException + } + case None => log.info(s"skipped ${getClass}") + } + } +} diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 096fd6cd4..9ef21a22b 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -4,7 +4,7 @@ import sbt.contraband.ContrabandPlugin.autoImport._ object Dependencies { val scala211 = "2.11.12" - val scala212 = "2.12.4" + val scala212 = "2.12.6" private val ioVersion = "1.1.3" private val utilVersion = "1.1.3" @@ -45,8 +45,8 @@ object Dependencies { val scalaReflect = Def.setting { "org.scala-lang" % "scala-reflect" % scalaVersion.value } val scalaCompiler = Def.setting { "org.scala-lang" % "scala-compiler" % scalaVersion.value } val scalaXml = scala211Module("scala-xml", "1.0.5") - val scalaTest = "org.scalatest" %% "scalatest" % "3.0.1" - val scalaCheck = "org.scalacheck" %% "scalacheck" % "1.13.4" + val scalaTest = "org.scalatest" %% "scalatest" % "3.0.5" + val scalaCheck = "org.scalacheck" %% "scalacheck" % "1.14.0" val sjsonnew = Def.setting { "com.eed3si9n" %% "sjson-new-core" % contrabandSjsonNewVersion.value } diff --git a/project/build.properties b/project/build.properties index 31334bbd3..64cf32f7f 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.1.1 +sbt.version=1.1.4 diff --git a/project/plugins.sbt b/project/plugins.sbt index 11a6aa3d4..f38b000fe 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.5") +addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.6") addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.4.0") addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.2") addSbtPlugin("com.lightbend" % "sbt-whitesource" % "0.1.9")