Найти хранилище, где sbt находит плагин или JAR - PullRequest
0 голосов
/ 26 декабря 2018

Пытаясь устранить неполадки при сборке sbt, хотелось бы узнать, какой шаблон в sbt.repositories соответствует данной тройке.

У меня есть плагин и две sbt сборки.Одна сборка находит плагин, а другая - нет.Обе сборки используют файлы sbt.repositories для переопределения внешних репозиториев внутренними сайтами (за корпоративным брандмауэром).

Файлы sbt.repositories различаются в двух сборках, поэтому я подозреваю, что в одной из них отсутствует шаблон, которыйбудет соответствовать плагину.Файлы sbt.repositories достаточно велики, и я бы предпочел не делать это вручную или методом проб и ошибок.

Я хотел бы использовать собственные средства sbt для печати сообщений, таких как «использованиеpattern (некоторый шаблон из sbt.repositories) Я нашел плагин (org, name, ver) в (некоторый URL) ".

Шаблоны из sbt.repositories имеют следующий формат.sbt должен проходить по этим шаблонам, вычислять все комбинации и проверять, является ли результат действительным URL.Я хотел бы получить доступ к этому классу сам, чтобы я мог узнать, какой шаблон из sbt.repositories позволяет одной сборке найти плагин (или JAR).Затем я добавил бы этот шаблон в sbt.repositories другой сборки.

Кто-нибудь знает, доступна ли эта функциональность через DSL сборки (т. Е. Из build.sbt) или имя класса преобразователя, который делаетэто для sbt?

sbt.repositories
repo-name = http://some.internal.website.com:1234/artifacts/releases,[organisation]/[module](/scala_[scalaVersion])(/sbt_[sbtVersion])/[revision]/[artifact](-[classifier])(-[revision]).[ext]

Я пробовал sbt -Dsbt.log.noformat=true --debug clean update compile > someLogFile.txt, и это говорит мне, какие плагины найдены, включая тот, который мне интересен, но не , где они былинайдено.

1 Ответ

0 голосов
/ 27 декабря 2018

написал что-то быстрое и грязное, но у меня это работает.Я был бы рад увидеть решение, которое использует распознаватель Ivy, который должен обеспечивать ту же функциональность, только более надежно.

По моему опыту, потому что людям трудно понять, является ли шаблон, подобный [organisation]/[module](/scala_[scalaVersion])(/sbt_[sbtVersion])/[revision]/[artifact](-[classifier])(-[revision]).[ext]соответствует тому, что им нужно, или дублирует другой шаблон, который уже существует в sbt.repositories, люди просто копируют и вставляют шаблоны из одного файла репо в другой, пока сборка не заработает.Со временем это создает запутанный беспорядок, и нам нужны инструменты для решения таких вопросов, как «какой шаблон соответствует данной зависимости» или «какие два шаблона идентичны» или «какой шаблон не соответствует ни одной зависимости» и т. Д.

import java.io.File
import java.net.URL
import java.util.regex.Pattern

import scala.collection.JavaConversions._
import scala.collection.mutable
import scala.io.{Codec, Source}
import scala.util.control.NonFatal

object FindDependency {

  def main(args: Array[String]): Unit = {
    val root = new File(".")
    val sbtRepos = new File(root, "./build/sbt.repositories")

    implicit val dep = Dep(organisation = "com.foo.bar.sbt", module = "baz", artifact = "baz", revision = "1.2.3-SNAPSHOT", ext = "jar"
      , scalaVersion = "2.10", sbtVersion = "0.13", artType = "jar", classifier = "")

    println(sbtRepos.getCanonicalPath + ": exists?" + sbtRepos.exists)
    processSbtRepos(sbtRepos)
  }

  def processSbtRepos(repoFilePath: File)(implicit dep: Dep): Unit = {
    val source = Source.fromFile(repoFilePath)(Codec.ISO8859)
    source.getLines.foreach { line =>
      if (!ignore(line)) {
        println(s"\n$line")
        val namePattern = line.split(":") map (_.trim)
        if (namePattern.length >= 3) artifactUrl(namePattern)
      }
    }
    source.close
  }

  def artifactUrl(words: Array[String])(implicit dep: Dep): Unit = {
    val artBase = repoUrl(words)
    val artifactPattern = if (artBase.indexOf('[') > 0) artBase else artBase + ",[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"
    val artUrls = dep.potentialUrls(artifactPattern)
    artUrls.foreach { url =>
      if (isValidUrl(url)) {
        println(s"$artifactPattern -> $url")
      }
    }
  }

  def isValidUrl(url: String): Boolean = {
    try {
      val u = new URL(url)
      val contentLength = u.openConnection.getContentLength
      val openStream = u.openStream
      val binaryData = new Array[Byte](contentLength)
      openStream.read(binaryData)
      openStream.close
      true
    } catch {
      case NonFatal(_) => false
    }
  }

  def repoUrl(words: Array[String]): String = words.drop(1).mkString(":")

  def ignore(line: String): Boolean = {
    line.indexOf("http://") < 0
  }

}

/**
  * Represents a dependency
  *
  * @param artType artifact type, e.g. "sources", "javadoc", ""
  */
case class Dep(organisation: String, module: String, artifact: String, revision: String
               , ext: String, scalaVersion: String, sbtVersion: String, artType: String
               , classifier: String) {
  /**
    * Given a pattern and the known parameters for a dependency, replace the details of the dependency in the pattern.
    *
    * @return a concrete URL (with optional portions) where the dependency may be located
    */
  def replace(pattern: String): String = {
    pattern.replaceAll(Pattern.quote("[artifact]"), artifact)
      .replaceAll(Pattern.quote("[ext]"), ext)
      .replaceAll(Pattern.quote("[module]"), module)
      .replaceAll(Pattern.quote("[organisation]"), organisation)
      .replaceAll(Pattern.quote("[organization]"), organisation)
      .replaceAll(Pattern.quote("[revision]"), revision)
      .replaceAll(Pattern.quote("[scalaVersion]"), scalaVersion)
      .replaceAll(Pattern.quote("[sbtVersion]"), sbtVersion)
      .replaceAll(Pattern.quote("[type]"), artType)
      .replaceAll(Pattern.quote("[classifier]"), classifier)
  }

  def potentialUrls(pattern: String): Seq[String] = {
    val urlWithOpts = replace(pattern)
      .replaceAll(" ", "")
      .replaceAll(",", "/")
      .replaceAll("\\(", "(?") // mark the optional elements with the prefix "?"
    val words = urlWithOpts.split("\\(|\\)").map(_.trim).filterNot(_.isEmpty).filterNot(_ == "?-")
    val urls = mutable.ArrayBuffer.empty[String]
    val urlsCrt = mutable.ArrayBuffer.empty[String] // a temp container for urls
    urls.add(words(0)) // the first "word" is the repo URL, which is not optional
    words.drop(1).foreach { word =>
      // transfer the current list of URLs to the temp container
      urlsCrt.clear
      urlsCrt ++= urls
      urls.clear
      if (word.startsWith("?")) {
        // append all URLs that were there before, unchanged (because this word is optional)
        urls ++= urlsCrt
        // as well as all URLs that were there before, each concatenated with this word
        urls ++= urlsCrt.map(_ + word.substring(1))
      } else {
        // to each URL that was there before, concatenate the new word
        urls ++= urlsCrt.map(_ + word)
      }
    }
    urls
  }
}
...