fix retrieving deps via sftp resolver

This commit is contained in:
OlegYch 2018-04-07 23:27:08 +03:00
parent 13807179ae
commit bbb2ef3977
3 changed files with 58 additions and 4 deletions

View File

@ -3,8 +3,8 @@ import Path._
import com.typesafe.tools.mima.core._, ProblemFilters._
val _ = {
//https://github.com/sbt/contraband/issues/122
sys.props += ("line.separator" -> "\n")
sys.props += ("file.separaror" -> "/")
}
def commonSettings: Seq[Setting[_]] = Seq(

View File

@ -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
}
@ -406,4 +407,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)
}
}
}

View File

@ -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}")
}
}
}