mirror of https://github.com/sbt/sbt.git
Merge pull request #439 from alexarchambault/topic/sbt-launcher
Add sbt launcher
This commit is contained in:
commit
b6295b2719
|
|
@ -1,48 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ev
|
||||
|
||||
# We're not using a jdk6 matrix entry with Travis here as some sources of coursier require Java 7 to compile
|
||||
# (even though it won't try to call Java 7 specific methods if it detects it runs under Java 6).
|
||||
# The tests here check that coursier is nonetheless fine when run under Java 6.
|
||||
|
||||
if echo "$TRAVIS_SCALA_VERSION" | grep -q "^2\.11"; then
|
||||
~/sbt ++${TRAVIS_SCALA_VERSION} cli/pack
|
||||
docker run -it --rm \
|
||||
-v $(pwd)/cli/target/pack:/opt/coursier \
|
||||
-e CI=true \
|
||||
openjdk:6-jre \
|
||||
/opt/coursier/bin/coursier fetch org.scalacheck::scalacheck:1.13.4
|
||||
|
||||
docker run -it --rm \
|
||||
-v $(pwd)/cli/target/pack:/opt/coursier \
|
||||
-e CI=true \
|
||||
openjdk:6-jre \
|
||||
/opt/coursier/bin/coursier launch --help
|
||||
fi
|
||||
|
||||
function clean_plugin_sbt() {
|
||||
mv plugins.sbt plugins.sbt0
|
||||
grep -v coursier plugins.sbt0 > plugins.sbt || true
|
||||
echo '
|
||||
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-SNAPSHOT")
|
||||
' >> plugins.sbt
|
||||
}
|
||||
|
||||
if echo "$TRAVIS_SCALA_VERSION" | grep -q "^2\.10"; then
|
||||
~/sbt ++${TRAVIS_SCALA_VERSION} publishLocal
|
||||
git clone https://github.com/alexarchambault/scalacheck-shapeless.git
|
||||
cd scalacheck-shapeless
|
||||
cd project
|
||||
clean_plugin_sbt
|
||||
cd project
|
||||
clean_plugin_sbt
|
||||
cd ../..
|
||||
docker run -it --rm \
|
||||
-v $HOME/.ivy2/local:/root/.ivy2/local \
|
||||
-v $HOME/sbt:/root/sbt \
|
||||
-v $(pwd):/root/project \
|
||||
-e CI=true \
|
||||
openjdk:6-jre \
|
||||
/bin/bash -c "cd /root/project && /root/sbt update"
|
||||
cd ..
|
||||
fi
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ev
|
||||
|
||||
TRAVIS_SCALA_VERSION="$1"
|
||||
shift
|
||||
TRAVIS_PULL_REQUEST="$1"
|
||||
shift
|
||||
TRAVIS_BRANCH="$1"
|
||||
shift
|
||||
PUBLISH="$1"
|
||||
shift
|
||||
|
||||
|
||||
function isNotPr() {
|
||||
[ "$TRAVIS_PULL_REQUEST" = "false" ]
|
||||
}
|
||||
|
||||
function publish() {
|
||||
[ "$PUBLISH" = 1 ]
|
||||
}
|
||||
|
||||
function isMaster() {
|
||||
[ "$TRAVIS_BRANCH" = "master" ]
|
||||
}
|
||||
|
||||
function isMasterOrDevelop() {
|
||||
[ "$TRAVIS_BRANCH" = "master" -o "$TRAVIS_BRANCH" = "develop" ]
|
||||
}
|
||||
|
||||
# Required for ~/.ivy2/local repo tests
|
||||
~/sbt ++2.11.8 coreJVM/publishLocal http-server/publishLocal
|
||||
|
||||
# Required for HTTP authentication tests
|
||||
./coursier launch \
|
||||
io.get-coursier:http-server-java7_2.11:1.0.0-SNAPSHOT \
|
||||
-r http://dl.bintray.com/scalaz/releases \
|
||||
-- \
|
||||
-d tests/jvm/src/test/resources/test-repo/http/abc.com \
|
||||
-u user -P pass -r realm \
|
||||
--list-pages \
|
||||
-v &
|
||||
|
||||
# TODO Add coverage once https://github.com/scoverage/sbt-scoverage/issues/111 is fixed
|
||||
|
||||
SBT_COMMANDS="compile test it:test"
|
||||
|
||||
RUN_SHADING_TESTS=1
|
||||
|
||||
if echo "$TRAVIS_SCALA_VERSION" | grep -q "^2\.10"; then
|
||||
SBT_COMMANDS="$SBT_COMMANDS publishLocal" # to make the scripted tests happy
|
||||
SBT_COMMANDS="$SBT_COMMANDS sbt-coursier/scripted"
|
||||
|
||||
if [ "$RUN_SHADING_TESTS" = 1 ]; then
|
||||
# for the shading scripted test
|
||||
sudo cp coursier /usr/local/bin/
|
||||
|
||||
JARJAR_VERSION=1.0.1-coursier-SNAPSHOT
|
||||
|
||||
if [ ! -d "$HOME/.m2/repository/org/anarres/jarjar/jarjar-core/$JARJAR_VERSION" ]; then
|
||||
git clone https://github.com/alexarchambault/jarjar.git
|
||||
cd jarjar
|
||||
if ! grep -q "^version=$JARJAR_VERSION\$" gradle.properties; then
|
||||
echo "Expected jarjar version not found" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
git checkout 249c8dbb970f8
|
||||
./gradlew :jarjar-core:install
|
||||
cd ..
|
||||
rm -rf jarjar
|
||||
fi
|
||||
|
||||
SBT_COMMANDS="$SBT_COMMANDS sbt-coursier/publishLocal sbt-shading/scripted"
|
||||
fi
|
||||
fi
|
||||
|
||||
SBT_COMMANDS="$SBT_COMMANDS tut coreJVM/mimaReportBinaryIssues cache/mimaReportBinaryIssues"
|
||||
|
||||
~/sbt ++${TRAVIS_SCALA_VERSION} $SBT_COMMANDS
|
||||
|
||||
.ci/java-6-test.sh
|
||||
|
||||
if isNotPr && publish && isMaster; then
|
||||
~/sbt ++${TRAVIS_SCALA_VERSION} publish
|
||||
fi
|
||||
|
||||
PUSH_GHPAGES=0
|
||||
if isNotPr && publish && isMasterOrDevelop; then
|
||||
if echo "$TRAVIS_SCALA_VERSION" | grep -q "^2\.11"; then
|
||||
PUSH_GHPAGES=1
|
||||
fi
|
||||
fi
|
||||
|
||||
# [ "$PUSH_GHPAGES" = 0 ] || "$(dirname "$0")/push-gh-pages.sh" "$TRAVIS_SCALA_VERSION"
|
||||
16
.travis.yml
16
.travis.yml
|
|
@ -1,12 +1,10 @@
|
|||
language: java
|
||||
install:
|
||||
- npm install
|
||||
- curl -L -o ~/sbt https://github.com/paulp/sbt-extras/raw/478a364a2d43d6e1ac4451f8b84cdafe43a2e43f/sbt
|
||||
- chmod +x ~/sbt
|
||||
os:
|
||||
- osx
|
||||
script:
|
||||
- .ci/travis.sh "${TRAVIS_SCALA_VERSION:-2.11.8}" "$TRAVIS_PULL_REQUEST" "$TRAVIS_BRANCH" "$PUBLISH"
|
||||
- scripts/travis.sh
|
||||
# Uncomment once https://github.com/scoverage/sbt-scoverage/issues/111 is fixed
|
||||
# after_success:
|
||||
# - bash <(curl -s https://codecov.io/bash)
|
||||
|
|
@ -27,9 +25,17 @@ matrix:
|
|||
sudo: required
|
||||
services:
|
||||
- docker
|
||||
- env: TRAVIS_SCALA_VERSION=2.12.1 PUBLISH=1 SCALA_JS=1
|
||||
os: linux
|
||||
jdk: oraclejdk8
|
||||
- env: TRAVIS_SCALA_VERSION=2.11.8 PUBLISH=1 SCALA_JS=1
|
||||
os: linux
|
||||
jdk: oraclejdk8
|
||||
- env: TRAVIS_SCALA_VERSION=2.10.6 PUBLISH=1 SCALA_JS=1
|
||||
os: linux
|
||||
jdk: oraclejdk8
|
||||
env:
|
||||
global:
|
||||
- COURSIER_NO_TERM=1
|
||||
- secure: miHFMwVRD/yjOLy794nOwc2lJTMyL5O0MXABT9ksg5ejQy1FrFVc2YH86Agp80W02/lGLGl0qWCiK1TBcs9q4Apt01nkD1a/0/iuTRm//bdhnu8BbRxFITf+2cyYJVytKPsF585aHldMv1rwZs3TDaTzEEecAEki5r50yyTVo7ycG0lVj9aVWXerKRMIT54Wb8M6nqbyRB1jGWT0ETNU13vOvQznPTUXQG5hsiKnGYRf8T3umOMdOHpV0rvdwYqAIMsikaAFcYCS5P/pLXMtmRHICH9KUG8TV/ST07p1BXtbBg9y1Q+lpnXotXh4ZNoWOp8B6v7fxJ/WlLYTDROWCiHJ4s2V4Di00db/nW4OWrEEBlrh7vJ/npZqyt9V9YeNv6alxi+DCESwusgvD4Cx5c3zh+2X6RB6BYwWHlFnd80rmsLe4R4fFUcc8E/ZR9vUFjP1CsQKqfJ5yfKR6V+n8jK8FjLpoaU9PHPo2H4V3FZM/fCLcxhE37vfaYI7/O7MqE/cdGpZIuz7g3c4toWCgNZJDn8iJCPmrgcbW5zbfDxvWU2K816ycgnUwSQ5dufrJpAbLNrjR1O8EPRkMDDp9bB7/4RVQvfDfP9GGoiHPHHgxGzY0Lf5bm+Bj1mRfB5/SXHd3IjhUCD9q7eD1/ANifEYALC5BJ4TB8RhQUPU8uM=
|
||||
- secure: 2/SSqa7A+aIzTJrMuqfK53QoHqes8HZPpIXUC9BH+bP2V2n7LqlFCnLZ9OSFfiJYfgeYMQDILpt8GTXHYc7JgM/N9xXpywrpYNDCYo7GMhqRyUPQOuK9044IRnZmme289Ut6ozHHptZUeZp/9DEUNZcPOxTN+KbzbHrUL+9l5BxnAxJ3e0HihxhmaINrla3T36EetdfINigarB9muyvuCRdRhZjwxsSF1fo5P+ZgWvAIDhPgNJH8eyjxHVbTabk7efPtWNWu0HjyOqJaIVk+TNjuQhvQPHKpYel0gVlCAfUjq7ZP8hZurfC6NjCFcnfTZ3d4R8GDcWJ47pgBWND8saIQOigNd7KHBPntD4fEJqgBSq3ZWakNBYzOtm8CxMGmiJHDCVqAEGzUG+lowN+SnPS2UluL3QtZ7oL/7MeJqCscH7sPwHtmZY+o0Muqo0ZJ2T2TzekQNYOAE7jeSzG1xOa/NNghny5fT+w6asPxfeolkMgyzuRFp1SLaLUf/XRV4fux0meGY9NIXso47xMSfAYVAAXT1FA2OOwmM1O4yvm3Ur95oEGDNw6z7MnWOSKS663WFwuw2cCaheCfAwvoa5jZUMWMbyUM/cBTgCaQdmETpvCzZzUr5Ls/nBXjyiTdJaQLZATr7HSGZHgYVmEAhVwBvuhTar/6VUZUMKGc2P4=
|
||||
- secure: NmXh4uxqvvqxYvOBOiXE131HajCYhJyd9+7kc1YjllRZVYG11YLah9Np7qnRUyugNOdcBnWVQGlfDHOFe8GHQsZKt5PvsIzxszTor0GeDQOePX3L4YXPkZRJatmoJJ0COxdI6weCAWkI6Zr934RsOndT0mO55gk9c6eeXCcLdNjAJ3izGQHy5Wb2KTzwMhBfwjdTQ0s65c1rzz5dZ/JODilWfTHiHsz+4sKwWVmAvXDTjePd0X3svX775ot23QesJgtaC/p0AKSLcHg3zEjKkJJvvLooQyNn/zU/bio/UatDZWXnNMsTBfEr3qUedjoOY65g3EX/vYlbNRkF3Itk0dpuPooTFmezJASI4ZpewBS9OvPZheMmU/dy5Bx//622x7p4MHyao9IvYmSX0C92VWEd3gwkSzKCJtBEz4Csd5BaGhzeL41di6NSVx4IEiehC9191G1wk4Yj7S2t69N6OdAJEq+znQlYISF5ogCqip7PuesBMYTW4FaIgpnfW/OYP6VpWW87ohw/dz/CcTzP9MzuoM249EHNZKTfnJrmPJBRYSn+W4y9sTgGElPhY1U/NVQ+C/9Fov1kHFD25WeTDPdZe6yCczaUrcvfTDitfo6qnWf8ZW5dJMXN744idaZ25AT/SGoCzkPXMe+us5XLTAOtrbBMP8NXLMv5OtU999E=
|
||||
|
|
@ -41,4 +47,4 @@ cache:
|
|||
- $HOME/.m2
|
||||
- $HOME/.ivy2/cache
|
||||
- $HOME/.sbt
|
||||
# Not adding $HOME/.coursier, we check that sbt-coursier works fine with an initially empty cache
|
||||
- $HOME/.coursier
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ install:
|
|||
}
|
||||
- cmd: SET PATH=C:\sbt\sbt\bin;%JAVA_HOME%\bin;%PATH%
|
||||
- cmd: SET SBT_OPTS=-XX:MaxPermSize=2g -Xmx4g
|
||||
- cmd: SET COURSIER_NO_TERM=1
|
||||
- ps: |
|
||||
if (!(Test-Path 'C:\Users\appveyor\.m2\repository\org\anarres\jarjar\jarjar-core\1.0.1-coursier-SNAPSHOT')) {
|
||||
iex 'git clone https://github.com/alexarchambault/jarjar'
|
||||
|
|
@ -35,3 +34,4 @@ cache:
|
|||
- C:\Users\appveyor\.ivy2\cache
|
||||
- C:\Users\appveyor\.m2
|
||||
- C:\Users\appveyor\.sbt
|
||||
- C:\Users\appveyor\.coursier
|
||||
|
|
|
|||
56
build.sbt
56
build.sbt
|
|
@ -3,6 +3,8 @@ import java.io.FileOutputStream
|
|||
val binaryCompatibilityVersion = "1.0.0-M14"
|
||||
val binaryCompatibility212Version = "1.0.0-M15"
|
||||
|
||||
parallelExecution in Global := false
|
||||
|
||||
lazy val IntegrationTest = config("it") extend Test
|
||||
|
||||
lazy val scalazVersion = "7.2.8"
|
||||
|
|
@ -162,6 +164,7 @@ lazy val cache = project
|
|||
import com.typesafe.tools.mima.core._
|
||||
|
||||
Seq(
|
||||
ProblemFilters.exclude[DirectMissingMethodProblem]("coursier.TermDisplay#UpdateDisplayRunnable.cleanDisplay"),
|
||||
ProblemFilters.exclude[FinalClassProblem]("coursier.TermDisplay$DownloadInfo"),
|
||||
ProblemFilters.exclude[FinalClassProblem]("coursier.TermDisplay$CheckUpdateInfo"),
|
||||
ProblemFilters.exclude[FinalClassProblem]("coursier.util.Base64$B64Scheme"),
|
||||
|
|
@ -205,6 +208,7 @@ lazy val cli = project
|
|||
else
|
||||
Seq()
|
||||
},
|
||||
packExcludeArtifactTypes += "pom",
|
||||
resourceGenerators in Compile += packageBin.in(bootstrap).in(Compile).map { jar =>
|
||||
Seq(jar)
|
||||
}.taskValue,
|
||||
|
|
@ -380,6 +384,19 @@ lazy val `sbt-shading` = project
|
|||
libraryDependencies += "org.anarres.jarjar" % "jarjar-core" % "1.0.0"
|
||||
)
|
||||
|
||||
lazy val `sbt-launcher` = project
|
||||
.dependsOn(cache)
|
||||
.settings(commonSettings)
|
||||
.settings(packAutoSettings)
|
||||
.settings(
|
||||
libraryDependencies ++= Seq(
|
||||
"com.github.alexarchambault" %% "case-app" % "1.1.3",
|
||||
"org.scala-sbt" % "launcher-interface" % "1.0.0",
|
||||
"com.typesafe" % "config" % "1.3.1"
|
||||
),
|
||||
packExcludeArtifactTypes += "pom"
|
||||
)
|
||||
|
||||
val http4sVersion = "0.8.6"
|
||||
|
||||
lazy val `http-server` = project
|
||||
|
|
@ -398,7 +415,8 @@ lazy val `http-server` = project
|
|||
)
|
||||
else
|
||||
Seq()
|
||||
}
|
||||
},
|
||||
packExcludeArtifactTypes += "pom"
|
||||
)
|
||||
|
||||
lazy val okhttp = project
|
||||
|
|
@ -411,6 +429,41 @@ lazy val okhttp = project
|
|||
)
|
||||
)
|
||||
|
||||
lazy val jvm = project
|
||||
.aggregate(
|
||||
coreJvm,
|
||||
testsJvm,
|
||||
cache,
|
||||
bootstrap,
|
||||
cli,
|
||||
`sbt-coursier`,
|
||||
`sbt-shading`,
|
||||
`sbt-launcher`,
|
||||
doc,
|
||||
`http-server`,
|
||||
okhttp
|
||||
)
|
||||
.settings(commonSettings)
|
||||
.settings(noPublishSettings)
|
||||
.settings(releaseSettings)
|
||||
.settings(
|
||||
moduleName := "coursier-jvm"
|
||||
)
|
||||
|
||||
lazy val js = project
|
||||
.aggregate(
|
||||
coreJs,
|
||||
`fetch-js`,
|
||||
testsJs,
|
||||
web
|
||||
)
|
||||
.settings(commonSettings)
|
||||
.settings(noPublishSettings)
|
||||
.settings(releaseSettings)
|
||||
.settings(
|
||||
moduleName := "coursier-js"
|
||||
)
|
||||
|
||||
lazy val `coursier` = project.in(file("."))
|
||||
.aggregate(
|
||||
coreJvm,
|
||||
|
|
@ -423,6 +476,7 @@ lazy val `coursier` = project.in(file("."))
|
|||
cli,
|
||||
`sbt-coursier`,
|
||||
`sbt-shading`,
|
||||
`sbt-launcher`,
|
||||
web,
|
||||
doc,
|
||||
`http-server`,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ object TermDisplay {
|
|||
def insideEmacs = sys.env.contains("INSIDE_EMACS")
|
||||
def ci = sys.env.contains("CI")
|
||||
|
||||
val env = env0.getOrElse(compatibilityEnv)
|
||||
val env = env0.fold(compatibilityEnv)(!_)
|
||||
|
||||
env || nonInteractive || insideEmacs || ci
|
||||
}
|
||||
|
|
@ -173,6 +173,8 @@ object TermDisplay {
|
|||
private var currentHeight = 0
|
||||
private var printedAnything0 = false
|
||||
|
||||
private var stopped = false
|
||||
|
||||
def printedAnything() = printedAnything0
|
||||
|
||||
private val needsUpdate = new AtomicBoolean(false)
|
||||
|
|
@ -286,7 +288,7 @@ object TermDisplay {
|
|||
}
|
||||
|
||||
private def updateDisplay(): Unit =
|
||||
if (needsUpdate.getAndSet(false)) {
|
||||
if (!stopped && needsUpdate.getAndSet(false)) {
|
||||
val (done0, downloads0) = downloads.synchronized {
|
||||
val q = doneQueue
|
||||
.toVector
|
||||
|
|
@ -341,13 +343,17 @@ object TermDisplay {
|
|||
currentHeight = downloads0.length
|
||||
}
|
||||
|
||||
def cleanDisplay(): Unit = {
|
||||
def stop(): Unit = {
|
||||
for (_ <- 1 to 2; _ <- 0 until currentHeight) {
|
||||
out.clearLine(2)
|
||||
out.down(1)
|
||||
}
|
||||
for (_ <- 0 until currentHeight)
|
||||
out.up(2)
|
||||
|
||||
out.flush()
|
||||
|
||||
stopped = true
|
||||
}
|
||||
|
||||
private var previous = Set.empty[String]
|
||||
|
|
@ -454,7 +460,7 @@ class TermDisplay(
|
|||
def stopDidPrintSomething(): Boolean = {
|
||||
scheduler.shutdown()
|
||||
scheduler.awaitTermination(2 * refreshInterval, TimeUnit.MILLISECONDS)
|
||||
updateRunnable.cleanDisplay()
|
||||
updateRunnable.stop()
|
||||
updateRunnable.printedAnything()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,10 +65,7 @@ final case class Bootstrap(
|
|||
sys.exit(1)
|
||||
}
|
||||
|
||||
val isolatedDeps = options.isolated.isolatedDeps(
|
||||
options.common.defaultArtifactType,
|
||||
options.common.scalaVersion
|
||||
)
|
||||
val isolatedDeps = options.isolated.isolatedDeps(options.common.scalaVersion)
|
||||
|
||||
val (_, isolatedArtifactFiles) =
|
||||
options.isolated.targets.foldLeft((Vector.empty[String], Map.empty[String, (Seq[String], Seq[File])])) {
|
||||
|
|
@ -81,7 +78,7 @@ final case class Bootstrap(
|
|||
def subFiles0 = helper.fetch(
|
||||
sources = false,
|
||||
javadoc = false,
|
||||
artifactTypes = artifactOptions.artifactTypes,
|
||||
artifactTypes = artifactOptions.artifactTypes(sources = false, javadoc = false),
|
||||
subset = isolatedDeps.getOrElse(target, Seq.empty).toSet
|
||||
)
|
||||
|
||||
|
|
@ -103,7 +100,7 @@ final case class Bootstrap(
|
|||
helper.fetch(
|
||||
sources = false,
|
||||
javadoc = false,
|
||||
artifactTypes = artifactOptions.artifactTypes
|
||||
artifactTypes = artifactOptions.artifactTypes(sources = false, javadoc = false)
|
||||
)
|
||||
)
|
||||
else
|
||||
|
|
@ -111,7 +108,7 @@ final case class Bootstrap(
|
|||
helper.artifacts(
|
||||
sources = false,
|
||||
javadoc = false,
|
||||
artifactTypes = artifactOptions.artifactTypes
|
||||
artifactTypes = artifactOptions.artifactTypes(sources = false, javadoc = false)
|
||||
).map(_.url),
|
||||
Seq.empty[File]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,12 @@ package coursier
|
|||
package cli
|
||||
|
||||
import caseapp._
|
||||
import caseapp.core.{ ArgsApp, CommandsMessages }
|
||||
import caseapp.core.{ ArgsApp, CommandMessages, CommandsMessages }
|
||||
import caseapp.core.util.pascalCaseSplit
|
||||
import caseapp.util.AnnotationOption
|
||||
|
||||
import shapeless._
|
||||
import shapeless.labelled.FieldType
|
||||
import shapeless.union.Union
|
||||
|
||||
// Temporary, see comment in Coursier below
|
||||
|
|
@ -21,10 +25,95 @@ final case class CoursierCommandHelper(
|
|||
object CoursierCommandHelper {
|
||||
type U = Union.`'bootstrap -> Bootstrap, 'fetch -> Fetch, 'launch -> Launch, 'resolve -> Resolve, 'sparksubmit -> SparkSubmit`.T
|
||||
|
||||
implicit val commandParser: CommandParser[CoursierCommandHelper] =
|
||||
CommandParser[U].map(CoursierCommandHelper(_))
|
||||
implicit val commandsMessages: CommandsMessages[CoursierCommandHelper] =
|
||||
CommandsMessages(CommandsMessages[U].messages)
|
||||
// Partially deriving these ones manually, to circumvent more-or-less random failures during auto derivation
|
||||
// Only running into those with the new custom sbt launcher though :-|
|
||||
|
||||
implicit def commandParser: CommandParser[CoursierCommandHelper] =
|
||||
CommandParser.ccons(
|
||||
Witness('bootstrap),
|
||||
AnnotationOption[CommandName, Bootstrap],
|
||||
Parser[Bootstrap],
|
||||
CommandParser.ccons(
|
||||
Witness('fetch),
|
||||
AnnotationOption[CommandName, Fetch],
|
||||
Parser[Fetch],
|
||||
CommandParser.ccons(
|
||||
Witness('launch),
|
||||
AnnotationOption[CommandName, Launch],
|
||||
Parser[Launch],
|
||||
CommandParser.ccons(
|
||||
Witness('resolve),
|
||||
AnnotationOption[CommandName, Resolve],
|
||||
Parser[Resolve],
|
||||
CommandParser.ccons(
|
||||
Witness('sparksubmit),
|
||||
AnnotationOption[CommandName, SparkSubmit],
|
||||
Parser[SparkSubmit],
|
||||
CommandParser.cnil
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
).map(CoursierCommandHelper(_))
|
||||
|
||||
|
||||
// Cut-n-pasted from caseapp.core.CommandsMessages.ccons, fixing the type of argsName
|
||||
private def commandsMessagesCCons[K <: Symbol, H, T <: Coproduct]
|
||||
(implicit
|
||||
key: Witness.Aux[K],
|
||||
commandName: AnnotationOption[CommandName, H],
|
||||
parser: Strict[Parser[H]],
|
||||
argsName: AnnotationOption[ArgsName, H],
|
||||
tail: CommandsMessages[T]
|
||||
): CommandsMessages[FieldType[K, H] :+: T] = {
|
||||
// FIXME Duplicated in CommandParser.ccons
|
||||
val name = commandName().map(_.commandName).getOrElse {
|
||||
pascalCaseSplit(key.value.name.toList.takeWhile(_ != '$'))
|
||||
.map(_.toLowerCase)
|
||||
.mkString("-")
|
||||
}
|
||||
|
||||
CommandsMessages((name -> CommandMessages(
|
||||
parser.value.args,
|
||||
argsName().map(_.argsName)
|
||||
)) +: tail.messages)
|
||||
}
|
||||
|
||||
|
||||
implicit def commandsMessages: CommandsMessages[CoursierCommandHelper] =
|
||||
CommandsMessages(
|
||||
commandsMessagesCCons(
|
||||
Witness('bootstrap),
|
||||
AnnotationOption[CommandName, Bootstrap],
|
||||
Parser[Bootstrap],
|
||||
AnnotationOption[ArgsName, Bootstrap],
|
||||
commandsMessagesCCons(
|
||||
Witness('fetch),
|
||||
AnnotationOption[CommandName, Fetch],
|
||||
Parser[Fetch],
|
||||
AnnotationOption[ArgsName, Fetch],
|
||||
commandsMessagesCCons(
|
||||
Witness('launch),
|
||||
AnnotationOption[CommandName, Launch],
|
||||
Parser[Launch],
|
||||
AnnotationOption[ArgsName, Launch],
|
||||
commandsMessagesCCons(
|
||||
Witness('resolve),
|
||||
AnnotationOption[CommandName, Resolve],
|
||||
Parser[Resolve],
|
||||
AnnotationOption[ArgsName, Resolve],
|
||||
commandsMessagesCCons(
|
||||
Witness('sparksubmit),
|
||||
AnnotationOption[CommandName, SparkSubmit],
|
||||
Parser[SparkSubmit],
|
||||
AnnotationOption[ArgsName, SparkSubmit],
|
||||
CommandsMessages.cnil
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
).messages
|
||||
)
|
||||
}
|
||||
|
||||
object Coursier extends CommandAppOf[
|
||||
|
|
|
|||
|
|
@ -17,7 +17,10 @@ final case class Fetch(
|
|||
val files0 = helper.fetch(
|
||||
sources = options.sources,
|
||||
javadoc = options.javadoc,
|
||||
artifactTypes = options.artifactOptions.artifactTypes
|
||||
artifactTypes = options.artifactOptions.artifactTypes(
|
||||
options.sources || options.common.classifier0("sources"),
|
||||
options.javadoc || options.common.classifier0("javadoc")
|
||||
)
|
||||
)
|
||||
|
||||
val out =
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ class Helper(
|
|||
Dependency(
|
||||
module,
|
||||
version,
|
||||
attributes = Attributes(defaultArtifactType, ""),
|
||||
attributes = Attributes("", ""),
|
||||
configuration = configOpt.getOrElse(defaultConfiguration),
|
||||
exclusions = excludes
|
||||
)
|
||||
|
|
@ -260,7 +260,7 @@ class Helper(
|
|||
Dependency(
|
||||
module,
|
||||
version,
|
||||
attributes = Attributes(defaultArtifactType, ""),
|
||||
attributes = Attributes("", ""),
|
||||
configuration = configOpt.getOrElse(defaultConfiguration),
|
||||
exclusions = excludes,
|
||||
transitive = false
|
||||
|
|
@ -523,11 +523,11 @@ class Helper(
|
|||
if (classifier0.nonEmpty || sources || javadoc) {
|
||||
var classifiers = classifier0
|
||||
if (sources)
|
||||
classifiers = classifiers :+ "sources"
|
||||
classifiers = classifiers + "sources"
|
||||
if (javadoc)
|
||||
classifiers = classifiers :+ "javadoc"
|
||||
classifiers = classifiers + "javadoc"
|
||||
|
||||
res0.dependencyClassifiersArtifacts(classifiers.distinct).map(_._2)
|
||||
res0.dependencyClassifiersArtifacts(classifiers.toVector.sorted).map(_._2)
|
||||
} else
|
||||
res0.dependencyArtifacts.map(_._2)
|
||||
|
||||
|
|
@ -616,7 +616,7 @@ class Helper(
|
|||
|
||||
// FIXME That shouldn't be hard-coded this way...
|
||||
// This whole class ought to be rewritten more cleanly.
|
||||
val artifactTypes = Set("jar")
|
||||
val artifactTypes = Set("jar", "bundle")
|
||||
|
||||
val files0 = fetch(
|
||||
sources = false,
|
||||
|
|
@ -628,7 +628,7 @@ class Helper(
|
|||
(baseLoader, files0)
|
||||
else {
|
||||
|
||||
val isolatedDeps = isolated.isolatedDeps(common.defaultArtifactType, common.scalaVersion)
|
||||
val isolatedDeps = isolated.isolatedDeps(common.scalaVersion)
|
||||
|
||||
val (isolatedLoader, filteredFiles0) = isolated.targets.foldLeft((baseLoader, files0)) {
|
||||
case ((parent, files0), target) =>
|
||||
|
|
|
|||
|
|
@ -61,10 +61,6 @@ final case class CommonOptions(
|
|||
@Value("configuration")
|
||||
@Short("c")
|
||||
defaultConfiguration: String = "default(compile)",
|
||||
@Help("Default artifact type (default: follow packaging infos, else default to jar)")
|
||||
@Value("type")
|
||||
@Short("a")
|
||||
defaultArtifactType: String = "",
|
||||
@Help("Maximum number of parallel downloads (default: 6)")
|
||||
@Short("n")
|
||||
parallel: Int = 6,
|
||||
|
|
@ -91,7 +87,7 @@ final case class CommonOptions(
|
|||
cacheOptions: CacheOptions = CacheOptions()
|
||||
) {
|
||||
val verbosityLevel = Tag.unwrap(verbose) - (if (quiet) 1 else 0)
|
||||
lazy val classifier0 = classifier.flatMap(_.split(',')).filter(_.nonEmpty)
|
||||
lazy val classifier0 = classifier.flatMap(_.split(',')).filter(_.nonEmpty).toSet
|
||||
}
|
||||
|
||||
final case class CacheOptions(
|
||||
|
|
@ -154,7 +150,7 @@ final case class IsolatedLoaderOptions(
|
|||
t -> modVers
|
||||
}
|
||||
|
||||
def isolatedDeps(defaultArtifactType: String, defaultScalaVersion: String) =
|
||||
def isolatedDeps(defaultScalaVersion: String) =
|
||||
isolatedModuleVersions(defaultScalaVersion).map {
|
||||
case (t, l) =>
|
||||
t -> l.map {
|
||||
|
|
@ -163,7 +159,7 @@ final case class IsolatedLoaderOptions(
|
|||
mod,
|
||||
ver,
|
||||
configuration = "runtime",
|
||||
attributes = Attributes(defaultArtifactType, "")
|
||||
attributes = Attributes("", "")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -182,15 +178,18 @@ final case class ArtifactOptions(
|
|||
@Help("Fetch artifacts even if the resolution is errored")
|
||||
force: Boolean = false
|
||||
) {
|
||||
lazy val artifactTypes = {
|
||||
def artifactTypes(sources: Boolean, javadoc: Boolean) = {
|
||||
val types0 = artifactType
|
||||
.flatMap(_.split(','))
|
||||
.filter(_.nonEmpty)
|
||||
.toSet
|
||||
|
||||
if (types0.isEmpty)
|
||||
ArtifactOptions.defaultArtifactTypes
|
||||
else if (types0("*"))
|
||||
if (types0.isEmpty) {
|
||||
if (sources || javadoc)
|
||||
Some("src").filter(_ => sources).toSet ++ Some("doc").filter(_ => javadoc)
|
||||
else
|
||||
ArtifactOptions.defaultArtifactTypes
|
||||
} else if (types0("*"))
|
||||
Set("*")
|
||||
else
|
||||
types0
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ final case class SparkSubmit(
|
|||
helper.fetch(
|
||||
sources = false,
|
||||
javadoc = false,
|
||||
artifactTypes = options.artifactOptions.artifactTypes
|
||||
artifactTypes = options.artifactOptions.artifactTypes(sources = false, javadoc = false)
|
||||
) ++ options.extraJars.map(new File(_))
|
||||
|
||||
val (scalaVersion, sparkVersion) =
|
||||
|
|
@ -195,7 +195,7 @@ final case class SparkSubmit(
|
|||
sparkVersion,
|
||||
options.noDefaultSubmitDependencies,
|
||||
options.submitDependencies.flatMap(_.split(",")).filter(_.nonEmpty),
|
||||
options.artifactOptions.artifactTypes,
|
||||
options.artifactOptions.artifactTypes(sources = false, javadoc = false),
|
||||
options.common
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ final case class IvyRepository(
|
|||
Map.empty,
|
||||
Map.empty,
|
||||
Attributes("", ""),
|
||||
changing = true,
|
||||
changing = changing.getOrElse(version.contains("-SNAPSHOT")),
|
||||
authentication
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ final case class MavenRepository(
|
|||
Map.empty,
|
||||
Map.empty,
|
||||
Attributes("", ""),
|
||||
changing = true,
|
||||
changing = changing.getOrElse(version.contains("-SNAPSHOT")),
|
||||
authentication
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ final case class MavenSource(
|
|||
project.publications.collect {
|
||||
case (_, p)
|
||||
if p.`type` == dependency.attributes.`type` ||
|
||||
p.ext == dependency.attributes.`type` // wow
|
||||
(p.ext == dependency.attributes.`type` && project.packagingOpt.toSeq.contains(p.`type`)) // wow
|
||||
=>
|
||||
p
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,10 +109,6 @@ object FromSbt {
|
|||
scalaBinaryVersion: String
|
||||
): Project = {
|
||||
|
||||
// FIXME Ignored for now - easy to support though
|
||||
// val sbtDepOverrides = dependencyOverrides.value
|
||||
// val sbtExclusions = excludeDependencies.value
|
||||
|
||||
val deps = allDependencies.flatMap(dependencies(_, scalaVersion, scalaBinaryVersion))
|
||||
|
||||
Project(
|
||||
|
|
@ -226,6 +222,9 @@ object FromSbt {
|
|||
mavenRepositoryOpt(mavenCompatibleBase, log, authentication)
|
||||
}
|
||||
|
||||
case raw: sbt.RawRepository if raw.name == "inter-project" => // sbt.RawRepository.equals just compares names anyway
|
||||
None
|
||||
|
||||
case other =>
|
||||
log.warn(s"Unrecognized repository ${other.name}, ignoring it")
|
||||
None
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
package coursier.sbtlauncher
|
||||
|
||||
import java.io.File
|
||||
|
||||
final case class AppConfiguration(
|
||||
arguments: Array[String],
|
||||
baseDirectory: File,
|
||||
provider: xsbti.AppProvider
|
||||
) extends xsbti.AppConfiguration
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package coursier.sbtlauncher
|
||||
|
||||
import java.io.File
|
||||
|
||||
final case class AppProvider(
|
||||
scalaProvider: xsbti.ScalaProvider,
|
||||
id: xsbti.ApplicationID,
|
||||
loader: ClassLoader,
|
||||
mainClass: Class[_ <: xsbti.AppMain],
|
||||
createMain: () => xsbti.AppMain,
|
||||
mainClasspath: Array[File],
|
||||
components: xsbti.ComponentProvider
|
||||
) extends xsbti.AppProvider {
|
||||
def entryPoint: Class[_] =
|
||||
mainClass
|
||||
def newMain(): xsbti.AppMain =
|
||||
createMain()
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package coursier.sbtlauncher
|
||||
|
||||
import java.io.File
|
||||
|
||||
final case class ApplicationID(
|
||||
groupID: String,
|
||||
name: String,
|
||||
version: String,
|
||||
mainClass: String,
|
||||
mainComponents: Array[String],
|
||||
crossVersioned: Boolean,
|
||||
crossVersionedValue: xsbti.CrossValue,
|
||||
classpathExtra: Array[File]
|
||||
) extends xsbti.ApplicationID {
|
||||
|
||||
assert(crossVersioned == (crossVersionedValue != xsbti.CrossValue.Disabled))
|
||||
|
||||
def disableCrossVersion(scalaVersion: String): ApplicationID =
|
||||
crossVersionedValue match {
|
||||
case xsbti.CrossValue.Disabled =>
|
||||
this
|
||||
case xsbti.CrossValue.Binary =>
|
||||
val scalaBinaryVersion = scalaVersion.split('.').take(2).mkString(".")
|
||||
copy(
|
||||
crossVersioned = false,
|
||||
crossVersionedValue = xsbti.CrossValue.Disabled,
|
||||
version = s"${version}_$scalaBinaryVersion"
|
||||
)
|
||||
case xsbti.CrossValue.Full =>
|
||||
copy(
|
||||
crossVersioned = false,
|
||||
crossVersionedValue = xsbti.CrossValue.Disabled,
|
||||
version = s"${version}_$scalaVersion"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object ApplicationID {
|
||||
def apply(id: xsbti.ApplicationID): ApplicationID =
|
||||
id match {
|
||||
case id0: ApplicationID => id0
|
||||
case _ =>
|
||||
ApplicationID(
|
||||
id.groupID(),
|
||||
id.name(),
|
||||
id.version(),
|
||||
id.mainClass(),
|
||||
id.mainComponents(),
|
||||
id.crossVersionedValue() != xsbti.CrossValue.Disabled,
|
||||
id.crossVersionedValue(),
|
||||
id.classpathExtra()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package coursier.sbtlauncher
|
||||
|
||||
import java.io.File
|
||||
import java.nio.file.{Files, StandardCopyOption}
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
final class ComponentProvider(cacheDir: File) extends xsbti.ComponentProvider {
|
||||
|
||||
private val components0 = new mutable.HashMap[String, Array[File]]
|
||||
|
||||
def componentLocation(id: String): File =
|
||||
new File(cacheDir, id)
|
||||
|
||||
def component(componentId: String): Array[File] = {
|
||||
val res = components0.getOrElse[Array[File]](
|
||||
componentId,
|
||||
{
|
||||
val dir = componentLocation(componentId)
|
||||
if (dir.exists())
|
||||
Option(dir.listFiles()).getOrElse(Array())
|
||||
else
|
||||
Array()
|
||||
}
|
||||
)
|
||||
res
|
||||
}
|
||||
|
||||
private def clear(componentId: String): Unit = {
|
||||
|
||||
def deleteRecursively(f: File): Unit =
|
||||
if (f.isFile)
|
||||
f.delete()
|
||||
else
|
||||
Option(f.listFiles())
|
||||
.getOrElse(Array())
|
||||
.foreach(deleteRecursively)
|
||||
|
||||
val dir = componentLocation(componentId)
|
||||
deleteRecursively(dir)
|
||||
}
|
||||
|
||||
private def copying(componentId: String, f: File): File = {
|
||||
|
||||
// TODO Use some locking mechanisms here
|
||||
|
||||
val dir = componentLocation(componentId)
|
||||
dir.mkdirs()
|
||||
val dest = new File(dir, f.getName)
|
||||
Files.copy(f.toPath, dest.toPath, StandardCopyOption.REPLACE_EXISTING)
|
||||
dest
|
||||
}
|
||||
|
||||
def defineComponentNoCopy(componentId: String, components: Array[File]): Unit = {
|
||||
components0 += componentId -> components.distinct
|
||||
}
|
||||
def defineComponent(componentId: String, components: Array[File]): Unit = {
|
||||
clear(componentId)
|
||||
components0 += componentId -> components.distinct.map(copying(componentId, _))
|
||||
}
|
||||
def addToComponent(componentId: String, components: Array[File]): Boolean = {
|
||||
val previousFiles = components0.getOrElse(componentId, Array.empty[File])
|
||||
val newFiles = (previousFiles ++ components.distinct.map(copying(componentId, _))).distinct
|
||||
components0 += componentId -> newFiles
|
||||
newFiles.length != previousFiles.length
|
||||
}
|
||||
|
||||
def lockFile: File = new File("/component-lock")
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package coursier.sbtlauncher
|
||||
|
||||
import java.io.File
|
||||
import java.util.concurrent.{Callable, ConcurrentHashMap}
|
||||
|
||||
case object DummyGlobalLock extends xsbti.GlobalLock {
|
||||
|
||||
private val locks = new ConcurrentHashMap[File, AnyRef]
|
||||
|
||||
def apply[T](lockFile: File, run: Callable[T]): T =
|
||||
Option(lockFile) match {
|
||||
case None => run.call()
|
||||
case Some(lockFile0) =>
|
||||
val lock0 = new AnyRef
|
||||
val lock = Option(locks.putIfAbsent(lockFile0, lock0)).getOrElse(lock0)
|
||||
|
||||
lock.synchronized {
|
||||
run.call()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,638 @@
|
|||
package coursier.sbtlauncher
|
||||
|
||||
import java.io.{File, OutputStreamWriter}
|
||||
import java.net.{URL, URLClassLoader}
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
import coursier.Cache.Logger
|
||||
import coursier._
|
||||
import coursier.ivy.IvyRepository
|
||||
import coursier.maven.MavenSource
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scalaz.{-\/, \/-}
|
||||
import scalaz.concurrent.Task
|
||||
|
||||
class Launcher(
|
||||
scalaVersion: String,
|
||||
componentsCache: File,
|
||||
val ivyHome: File
|
||||
) extends xsbti.Launcher {
|
||||
|
||||
val componentProvider = new ComponentProvider(componentsCache)
|
||||
|
||||
lazy val baseLoader = {
|
||||
|
||||
@tailrec
|
||||
def rootLoader(cl: ClassLoader): ClassLoader =
|
||||
if (cl == null)
|
||||
sys.error("Cannot find base loader")
|
||||
else {
|
||||
val isLauncherLoader =
|
||||
try {
|
||||
cl
|
||||
.asInstanceOf[AnyRef { def getIsolationTargets: Array[String] }]
|
||||
.getIsolationTargets
|
||||
.contains("launcher")
|
||||
} catch {
|
||||
case _: Throwable => false
|
||||
}
|
||||
|
||||
if (isLauncherLoader)
|
||||
cl
|
||||
else
|
||||
rootLoader(cl.getParent)
|
||||
}
|
||||
|
||||
rootLoader(Thread.currentThread().getContextClassLoader)
|
||||
}
|
||||
|
||||
val repositoryIdPrefix = "coursier-launcher-"
|
||||
|
||||
val repositories = Seq(
|
||||
// mmh, ID "local" seems to be required for publishLocal to be fine if we're launching sbt
|
||||
"local" -> Cache.ivy2Local,
|
||||
s"${repositoryIdPrefix}central" -> MavenRepository("https://repo1.maven.org/maven2", sbtAttrStub = true),
|
||||
s"${repositoryIdPrefix}typesafe-ivy-releases" -> IvyRepository.parse(
|
||||
"https://repo.typesafe.com/typesafe/ivy-releases/[organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext]"
|
||||
).leftMap(sys.error).merge,
|
||||
s"${repositoryIdPrefix}sbt-plugin-releases" -> IvyRepository.parse(
|
||||
"https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/[organization]/[module](/scala_[scalaVersion])(/sbt_[sbtVersion])/[revision]/[type]s/[artifact](-[classifier]).[ext]"
|
||||
).leftMap(sys.error).merge
|
||||
)
|
||||
|
||||
assert(!repositories.groupBy(_._1).exists(_._2.lengthCompare(1) > 0))
|
||||
|
||||
val cachePolicies = CachePolicy.default
|
||||
|
||||
def fetch(logger: Option[Logger]) = {
|
||||
def helper(policy: CachePolicy) =
|
||||
Cache.fetch(cachePolicy = policy, logger = logger)
|
||||
|
||||
val f = cachePolicies.map(helper)
|
||||
|
||||
Fetch.from(repositories.map(_._2), f.head, f.tail: _*)
|
||||
}
|
||||
|
||||
val keepArtifactTypes = Set("jar", "bundle")
|
||||
|
||||
def tasks(res: Resolution, logger: Option[Logger], classifiersOpt: Option[Seq[String]] = None) = {
|
||||
val a = classifiersOpt
|
||||
.fold(res.dependencyArtifacts.map(_._2))(res.dependencyClassifiersArtifacts(_).map(_._2))
|
||||
|
||||
val keepArtifactTypes = classifiersOpt.fold(Set("jar", "bundle"))(c => c.map(c => MavenSource.classifierExtensionDefaultTypes.getOrElse((c, "jar"), ???)).toSet)
|
||||
|
||||
a.collect {
|
||||
case artifact if keepArtifactTypes(artifact.`type`) =>
|
||||
def file(policy: CachePolicy) = Cache.file(
|
||||
artifact,
|
||||
cachePolicy = policy,
|
||||
logger = logger
|
||||
)
|
||||
|
||||
(file(cachePolicies.head) /: cachePolicies.tail)(_ orElse file(_))
|
||||
.run
|
||||
.map(artifact.->)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def isOverrideRepositories = false // ???
|
||||
|
||||
def bootDirectory: File = ???
|
||||
|
||||
def getScala(version: String): xsbti.ScalaProvider =
|
||||
getScala(version, "")
|
||||
|
||||
def getScala(version: String, reason: String): xsbti.ScalaProvider =
|
||||
getScala(version, reason, "org.scala-lang")
|
||||
|
||||
def getScala(version: String, reason: String, scalaOrg: String): xsbti.ScalaProvider = {
|
||||
|
||||
val key = (version, scalaOrg)
|
||||
|
||||
Option(scalaProviderCache.get(key)).getOrElse {
|
||||
val prov = getScala0(version, reason, scalaOrg)
|
||||
val previous = Option(scalaProviderCache.putIfAbsent(key, prov))
|
||||
previous.getOrElse(prov)
|
||||
}
|
||||
}
|
||||
|
||||
private val scalaProviderCache = new ConcurrentHashMap[(String, String), xsbti.ScalaProvider]
|
||||
|
||||
private def getScala0(version: String, reason: String, scalaOrg: String): xsbti.ScalaProvider = {
|
||||
|
||||
val files = getScalaFiles(version, reason, scalaOrg)
|
||||
|
||||
val libraryJar = files.find(_.getName.startsWith("scala-library")).getOrElse {
|
||||
throw new NoSuchElementException("scala-library JAR")
|
||||
}
|
||||
val compilerJar = files.find(_.getName.startsWith("scala-compiler")).getOrElse {
|
||||
throw new NoSuchElementException("scala-compiler JAR")
|
||||
}
|
||||
|
||||
val scalaLoader = new URLClassLoader(files.map(_.toURI.toURL).toArray, baseLoader)
|
||||
|
||||
ScalaProvider(
|
||||
this,
|
||||
version,
|
||||
scalaLoader,
|
||||
files.toArray,
|
||||
libraryJar,
|
||||
compilerJar,
|
||||
id => app(id, id.version())
|
||||
)
|
||||
}
|
||||
|
||||
private def getScalaFiles(version: String, reason: String, scalaOrg: String): Seq[File] = {
|
||||
|
||||
val initialRes = Resolution(
|
||||
Set(
|
||||
Dependency(Module(scalaOrg, "scala-library"), version),
|
||||
Dependency(Module(scalaOrg, "scala-compiler"), version)
|
||||
),
|
||||
forceVersions = Map(
|
||||
Module(scalaOrg, "scala-library") -> version,
|
||||
Module(scalaOrg, "scala-compiler") -> version,
|
||||
Module(scalaOrg, "scala-reflect") -> version
|
||||
)
|
||||
)
|
||||
|
||||
val logger =
|
||||
Some(new TermDisplay(
|
||||
new OutputStreamWriter(System.err)
|
||||
))
|
||||
|
||||
logger.foreach(_.init {
|
||||
System.err.println(s"Resolving Scala $version (organization $scalaOrg)")
|
||||
})
|
||||
|
||||
val res = initialRes.process.run(fetch(logger)).unsafePerformSync
|
||||
|
||||
logger.foreach { l =>
|
||||
if (l.stopDidPrintSomething())
|
||||
System.err.println(s"Resolved Scala $version (organization $scalaOrg)")
|
||||
}
|
||||
|
||||
if (res.errors.nonEmpty) {
|
||||
Console.err.println(s"Errors:\n${res.errors.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
if (res.conflicts.nonEmpty) {
|
||||
Console.err.println(s"Conflicts:\n${res.conflicts.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
if (!res.isDone) {
|
||||
Console.err.println("Did not converge")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
val artifactLogger =
|
||||
Some(new TermDisplay(
|
||||
new OutputStreamWriter(System.err)
|
||||
))
|
||||
|
||||
artifactLogger.foreach(_.init {
|
||||
System.err.println(s"Fetching Scala $version artifacts (organization $scalaOrg)")
|
||||
})
|
||||
|
||||
val results = Task.gatherUnordered(tasks(res, artifactLogger)).unsafePerformSync
|
||||
|
||||
artifactLogger.foreach { l =>
|
||||
if (l.stopDidPrintSomething())
|
||||
System.err.println(s"Fetched Scala $version artifacts (organization $scalaOrg)")
|
||||
}
|
||||
|
||||
val errors = results.collect { case (a, -\/(err)) => (a, err) }
|
||||
val files = results.collect { case (_, \/-(f)) => f }
|
||||
|
||||
if (errors.nonEmpty) {
|
||||
Console.err.println(s"Error downloading artifacts:\n${errors.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
files
|
||||
}
|
||||
|
||||
def topLoader: ClassLoader = baseLoader
|
||||
|
||||
def appRepositories: Array[xsbti.Repository] =
|
||||
repositories.map {
|
||||
case (id, m: MavenRepository) =>
|
||||
Repository.Maven(id, new URL(m.root))
|
||||
case (id, i: IvyRepository) =>
|
||||
|
||||
assert(i.metadataPatternOpt.forall(_ == i.pattern))
|
||||
|
||||
val (base, pat) = i.pattern.string.span(c => c != '[' && c != '$' && c != '(')
|
||||
|
||||
assert(base.nonEmpty, i.pattern.string)
|
||||
|
||||
Repository.Ivy(
|
||||
id,
|
||||
new URL(base),
|
||||
pat,
|
||||
pat,
|
||||
mavenCompatible = false,
|
||||
skipConsistencyCheck = true, // ???
|
||||
descriptorOptional = true // ???
|
||||
)
|
||||
}.toArray
|
||||
|
||||
def ivyRepositories: Array[xsbti.Repository] =
|
||||
appRepositories // ???
|
||||
|
||||
def globalLock = DummyGlobalLock
|
||||
|
||||
// See https://github.com/sbt/ivy/blob/2cf13e211b2cb31f0d3b317289dca70eca3362f6/src/java/org/apache/ivy/util/ChecksumHelper.java
|
||||
def checksums: Array[String] = Array("sha1", "md5")
|
||||
|
||||
def app(id: xsbti.ApplicationID, version: String): xsbti.AppProvider =
|
||||
app(ApplicationID(id).copy(version = version))
|
||||
|
||||
def app(id: xsbti.ApplicationID, extra: Dependency*): xsbti.AppProvider = {
|
||||
|
||||
val (scalaFiles, files) = appFiles(id, extra: _*)
|
||||
|
||||
val scalaLoader = new URLClassLoader(scalaFiles.map(_.toURI.toURL).toArray, baseLoader)
|
||||
|
||||
val libraryJar = scalaFiles.find(_.getName.startsWith("scala-library")).getOrElse {
|
||||
throw new NoSuchElementException("scala-library JAR")
|
||||
}
|
||||
val compilerJar = scalaFiles.find(_.getName.startsWith("scala-compiler")).getOrElse {
|
||||
throw new NoSuchElementException("scala-compiler JAR")
|
||||
}
|
||||
|
||||
val scalaProvider = ScalaProvider(
|
||||
this,
|
||||
scalaVersion,
|
||||
scalaLoader,
|
||||
scalaFiles.toArray,
|
||||
libraryJar,
|
||||
compilerJar,
|
||||
id => app(id, id.version())
|
||||
)
|
||||
|
||||
val loader = new URLClassLoader(files.filterNot(scalaFiles.toSet).map(_.toURI.toURL).toArray, scalaLoader)
|
||||
val mainClass0 = loader.loadClass(id.mainClass).asSubclass(classOf[xsbti.AppMain])
|
||||
|
||||
AppProvider(
|
||||
scalaProvider,
|
||||
id,
|
||||
loader,
|
||||
mainClass0,
|
||||
() => mainClass0.newInstance(),
|
||||
files.toArray,
|
||||
componentProvider
|
||||
)
|
||||
}
|
||||
|
||||
private def appFiles(id: xsbti.ApplicationID, extra: Dependency*): (Seq[File], Seq[File]) = {
|
||||
|
||||
val id0 = ApplicationID(id).disableCrossVersion(scalaVersion)
|
||||
|
||||
val initialRes = Resolution(
|
||||
Set(
|
||||
Dependency(Module("org.scala-lang", "scala-library"), scalaVersion),
|
||||
Dependency(Module("org.scala-lang", "scala-compiler"), scalaVersion),
|
||||
Dependency(Module(id0.groupID, id0.name), id0.version)
|
||||
) ++ extra,
|
||||
forceVersions = Map(
|
||||
Module("org.scala-lang", "scala-library") -> scalaVersion,
|
||||
Module("org.scala-lang", "scala-compiler") -> scalaVersion,
|
||||
Module("org.scala-lang", "scala-reflect") -> scalaVersion
|
||||
)
|
||||
)
|
||||
|
||||
val logger =
|
||||
Some(new TermDisplay(
|
||||
new OutputStreamWriter(System.err)
|
||||
))
|
||||
|
||||
val extraMsg =
|
||||
if (extra.isEmpty)
|
||||
""
|
||||
else
|
||||
s" (plus ${extra.length} dependencies)"
|
||||
|
||||
logger.foreach(_.init {
|
||||
System.err.println(s"Resolving ${id0.groupID}:${id0.name}:${id0.version}$extraMsg")
|
||||
})
|
||||
|
||||
val res = initialRes.process.run(fetch(logger)).unsafePerformSync
|
||||
|
||||
logger.foreach { l =>
|
||||
if (l.stopDidPrintSomething())
|
||||
System.err.println(s"Resolved ${id0.groupID}:${id0.name}:${id0.version}$extraMsg")
|
||||
}
|
||||
|
||||
if (res.errors.nonEmpty) {
|
||||
Console.err.println(s"Errors:\n${res.errors.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
if (res.conflicts.nonEmpty) {
|
||||
Console.err.println(s"Conflicts:\n${res.conflicts.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
if (!res.isDone) {
|
||||
Console.err.println("Did not converge")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
val artifactLogger =
|
||||
Some(new TermDisplay(
|
||||
new OutputStreamWriter(System.err)
|
||||
))
|
||||
|
||||
artifactLogger.foreach(_.init {
|
||||
System.err.println(s"Fetching ${id0.groupID}:${id0.name}:${id0.version} artifacts")
|
||||
})
|
||||
|
||||
val results = Task.gatherUnordered(tasks(res, artifactLogger)).unsafePerformSync
|
||||
|
||||
artifactLogger.foreach { l =>
|
||||
if (l.stopDidPrintSomething())
|
||||
System.err.println(s"Fetched ${id0.groupID}:${id0.name}:${id0.version} artifacts")
|
||||
}
|
||||
|
||||
val errors = results.collect { case (a, -\/(err)) => (a, err) }
|
||||
val files = results.collect { case (_, \/-(f)) => f }
|
||||
|
||||
if (errors.nonEmpty) {
|
||||
Console.err.println(s"Error downloading artifacts:\n${errors.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
val scalaSubRes = res.subset(
|
||||
Set(
|
||||
Dependency(Module("org.scala-lang", "scala-library"), scalaVersion),
|
||||
Dependency(Module("org.scala-lang", "scala-compiler"), scalaVersion)
|
||||
)
|
||||
)
|
||||
|
||||
val scalaArtifactLogger =
|
||||
Some(new TermDisplay(
|
||||
new OutputStreamWriter(System.err)
|
||||
))
|
||||
|
||||
scalaArtifactLogger.foreach(_.init {
|
||||
System.err.println(s"Fetching ${id0.groupID}:${id0.name}:${id0.version} Scala artifacts")
|
||||
})
|
||||
|
||||
val scalaResults = Task.gatherUnordered(tasks(scalaSubRes, scalaArtifactLogger)).unsafePerformSync
|
||||
|
||||
scalaArtifactLogger.foreach { l =>
|
||||
if (l.stopDidPrintSomething())
|
||||
System.err.println(s"Fetched ${id0.groupID}:${id0.name}:${id0.version} Scala artifacts")
|
||||
}
|
||||
|
||||
val scalaErrors = scalaResults.collect { case (a, -\/(err)) => (a, err) }
|
||||
val scalaFiles = scalaResults.collect { case (_, \/-(f)) => f }
|
||||
|
||||
if (scalaErrors.nonEmpty) {
|
||||
Console.err.println(s"Error downloading artifacts:\n${scalaErrors.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
(scalaFiles, files)
|
||||
}
|
||||
|
||||
def registerScalaComponents(scalaVersion: String = scalaVersion): Unit = {
|
||||
|
||||
lazy val prov = getScala(scalaVersion)
|
||||
lazy val jars = prov.jars()
|
||||
|
||||
lazy val libraryJar = jars.find(_.getName.startsWith("scala-library")).getOrElse {
|
||||
throw new NoSuchElementException("scala-library JAR")
|
||||
}
|
||||
lazy val compilerJar = jars.find(_.getName.startsWith("scala-compiler")).getOrElse {
|
||||
throw new NoSuchElementException("scala-compiler JAR")
|
||||
}
|
||||
lazy val reflectJar = jars.find(_.getName.startsWith("scala-reflect")).getOrElse {
|
||||
throw new NoSuchElementException("scala-reflect JAR")
|
||||
}
|
||||
|
||||
if (componentProvider.component("library").isEmpty)
|
||||
componentProvider.defineComponentNoCopy("library", Array(libraryJar))
|
||||
if (componentProvider.component("compiler").isEmpty)
|
||||
componentProvider.defineComponentNoCopy("compiler", Array(compilerJar))
|
||||
if (componentProvider.component("reflect").isEmpty)
|
||||
componentProvider.defineComponentNoCopy("reflect", Array(reflectJar))
|
||||
}
|
||||
|
||||
def registerSbtInterfaceComponents(sbtVersion: String): Unit = {
|
||||
|
||||
lazy val (interfaceJar, _) = sbtInterfaceComponentFiles(sbtVersion)
|
||||
lazy val compilerInterfaceSourceJar = sbtCompilerInterfaceSrcComponentFile(sbtVersion)
|
||||
|
||||
if (componentProvider.component("xsbti").isEmpty)
|
||||
componentProvider.defineComponentNoCopy("xsbti", Array(interfaceJar))
|
||||
if (componentProvider.component("compiler-interface").isEmpty)
|
||||
componentProvider.defineComponentNoCopy("compiler-interface", Array(compilerInterfaceSourceJar))
|
||||
if (componentProvider.component("compiler-interface-src").isEmpty)
|
||||
componentProvider.defineComponentNoCopy("compiler-interface-src", Array(compilerInterfaceSourceJar))
|
||||
}
|
||||
|
||||
private def sbtInterfaceComponentFiles(sbtVersion: String): (File, File) = {
|
||||
|
||||
lazy val res = {
|
||||
|
||||
val initialRes = Resolution(
|
||||
Set(
|
||||
Dependency(Module("org.scala-sbt", "interface"), sbtVersion, transitive = false)
|
||||
)
|
||||
)
|
||||
|
||||
val logger =
|
||||
Some(new TermDisplay(
|
||||
new OutputStreamWriter(System.err)
|
||||
))
|
||||
|
||||
logger.foreach(_.init {
|
||||
System.err.println(s"Resolving org.scala-sbt:interface:$sbtVersion")
|
||||
})
|
||||
|
||||
val res = initialRes.process.run(fetch(logger)).unsafePerformSync
|
||||
|
||||
logger.foreach { l =>
|
||||
if (l.stopDidPrintSomething())
|
||||
System.err.println(s"Resolved org.scala-sbt:interface:$sbtVersion")
|
||||
}
|
||||
|
||||
if (res.errors.nonEmpty) {
|
||||
Console.err.println(s"Errors:\n${res.errors.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
if (res.conflicts.nonEmpty) {
|
||||
Console.err.println(s"Conflicts:\n${res.conflicts.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
if (!res.isDone) {
|
||||
Console.err.println("Did not converge")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
lazy val interfaceJar = {
|
||||
|
||||
val artifactLogger =
|
||||
Some(new TermDisplay(
|
||||
new OutputStreamWriter(System.err)
|
||||
))
|
||||
|
||||
artifactLogger.foreach(_.init {
|
||||
System.err.println(s"Fetching org.scala-sbt:interface:$sbtVersion artifacts")
|
||||
})
|
||||
|
||||
val results = Task.gatherUnordered(tasks(res, artifactLogger)).unsafePerformSync
|
||||
|
||||
artifactLogger.foreach { l =>
|
||||
if (l.stopDidPrintSomething())
|
||||
System.err.println(s"Fetched org.scala-sbt:interface:$sbtVersion artifacts")
|
||||
}
|
||||
|
||||
val errors = results.collect { case (a, -\/(err)) => (a, err) }
|
||||
val files = results.collect { case (_, \/-(f)) => f }
|
||||
|
||||
if (errors.nonEmpty) {
|
||||
Console.err.println(s"Error downloading artifacts:\n${errors.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
files match {
|
||||
case Nil =>
|
||||
throw new NoSuchElementException(s"interface JAR for sbt $sbtVersion")
|
||||
case List(jar) =>
|
||||
jar
|
||||
case _ =>
|
||||
sys.error(s"Too many interface JAR for sbt $sbtVersion: ${files.mkString(", ")}")
|
||||
}
|
||||
}
|
||||
|
||||
lazy val compilerInterfaceSourcesJar = {
|
||||
|
||||
val artifactLogger =
|
||||
Some(new TermDisplay(
|
||||
new OutputStreamWriter(System.err)
|
||||
))
|
||||
|
||||
artifactLogger.foreach(_.init {
|
||||
System.err.println(s"Fetching org.scala-sbt:interface:$sbtVersion source artifacts")
|
||||
})
|
||||
|
||||
val results = Task.gatherUnordered(tasks(res, artifactLogger, Some(Seq("sources")))).unsafePerformSync
|
||||
|
||||
artifactLogger.foreach { l =>
|
||||
if (l.stopDidPrintSomething())
|
||||
System.err.println(s"Fetched org.scala-sbt:interface:$sbtVersion source artifacts")
|
||||
}
|
||||
|
||||
val errors = results.collect { case (a, -\/(err)) => (a, err) }
|
||||
val files = results.collect { case (_, \/-(f)) => f }
|
||||
|
||||
if (errors.nonEmpty) {
|
||||
Console.err.println(s"Error downloading artifacts:\n${errors.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
files match {
|
||||
case Nil =>
|
||||
throw new NoSuchElementException(s"compiler-interface source JAR for sbt $sbtVersion")
|
||||
case List(jar) =>
|
||||
jar
|
||||
case _ =>
|
||||
sys.error(s"Too many compiler-interface source JAR for sbt $sbtVersion: ${files.mkString(", ")}")
|
||||
}
|
||||
}
|
||||
|
||||
(interfaceJar, compilerInterfaceSourcesJar)
|
||||
}
|
||||
|
||||
private def sbtCompilerInterfaceSrcComponentFile(sbtVersion: String): File = {
|
||||
|
||||
val res = {
|
||||
|
||||
val initialRes = Resolution(
|
||||
Set(
|
||||
Dependency(Module("org.scala-sbt", "compiler-interface"), sbtVersion, transitive = false)
|
||||
)
|
||||
)
|
||||
|
||||
val logger =
|
||||
Some(new TermDisplay(
|
||||
new OutputStreamWriter(System.err)
|
||||
))
|
||||
|
||||
logger.foreach(_.init {
|
||||
System.err.println(s"Resolving org.scala-sbt:compiler-interface:$sbtVersion")
|
||||
})
|
||||
|
||||
val res = initialRes.process.run(fetch(logger)).unsafePerformSync
|
||||
|
||||
logger.foreach { l =>
|
||||
if (l.stopDidPrintSomething())
|
||||
System.err.println(s"Resolved org.scala-sbt:compiler-interface:$sbtVersion")
|
||||
}
|
||||
|
||||
if (res.errors.nonEmpty) {
|
||||
Console.err.println(s"Errors:\n${res.errors.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
if (res.conflicts.nonEmpty) {
|
||||
Console.err.println(s"Conflicts:\n${res.conflicts.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
if (!res.isDone) {
|
||||
Console.err.println("Did not converge")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
val files = {
|
||||
|
||||
val artifactLogger =
|
||||
Some(new TermDisplay(
|
||||
new OutputStreamWriter(System.err)
|
||||
))
|
||||
|
||||
artifactLogger.foreach(_.init {
|
||||
System.err.println(s"Fetching org.scala-sbt:compiler-interface:$sbtVersion source artifacts")
|
||||
})
|
||||
|
||||
val results = Task.gatherUnordered(
|
||||
tasks(res, artifactLogger, None) ++
|
||||
tasks(res, artifactLogger, Some(Seq("sources")))
|
||||
).unsafePerformSync
|
||||
|
||||
artifactLogger.foreach { l =>
|
||||
if (l.stopDidPrintSomething())
|
||||
System.err.println(s"Fetched org.scala-sbt:compiler-interface:$sbtVersion source artifacts")
|
||||
}
|
||||
|
||||
val errors = results.collect { case (a, -\/(err)) => (a, err) }
|
||||
|
||||
if (errors.nonEmpty) {
|
||||
Console.err.println(s"Error downloading artifacts:\n${errors.map(" " + _).mkString("\n")}")
|
||||
sys.exit(1)
|
||||
}
|
||||
|
||||
results.collect { case (_, \/-(f)) => f }
|
||||
}
|
||||
|
||||
files.find(f => f.getName == "compiler-interface-src.jar" || f.getName == "compiler-interface-sources.jar").getOrElse {
|
||||
sys.error("compiler-interface-src not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package coursier.sbtlauncher
|
||||
|
||||
import java.io.File
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Files
|
||||
|
||||
import caseapp._
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import coursier.Dependency
|
||||
|
||||
final case class MainApp(
|
||||
@ExtraName("org")
|
||||
organization: String,
|
||||
name: String,
|
||||
version: String,
|
||||
scalaVersion: String,
|
||||
sbtVersion: String,
|
||||
mainClass: String,
|
||||
mainComponents: List[String],
|
||||
classpathExtra: List[String],
|
||||
extra: List[String]
|
||||
) extends App {
|
||||
|
||||
val sbtPropFile = new File(sys.props("user.dir") + "/sbt.properties")
|
||||
val buildPropFile = new File(sys.props("user.dir") + "/project/build.properties")
|
||||
|
||||
val propFileOpt = Some(sbtPropFile).filter(_.exists())
|
||||
.orElse(Some(buildPropFile).filter(_.exists()))
|
||||
|
||||
val (org0, name0, ver0, scalaVer0, extraDeps0, mainClass0, sbtVersion0) =
|
||||
propFileOpt match {
|
||||
case Some(propFile) =>
|
||||
// can't get ConfigFactory.parseFile to work fine here
|
||||
val conf = ConfigFactory.parseString(new String(Files.readAllBytes(propFile.toPath), StandardCharsets.UTF_8))
|
||||
.withFallback(ConfigFactory.defaultReference(Thread.currentThread().getContextClassLoader))
|
||||
.resolve()
|
||||
val sbtConfig = SbtConfig.fromConfig(conf)
|
||||
|
||||
(sbtConfig.organization, sbtConfig.moduleName, sbtConfig.version, sbtConfig.scalaVersion, sbtConfig.dependencies, sbtConfig.mainClass, sbtConfig.version)
|
||||
case None =>
|
||||
require(scalaVersion.nonEmpty, "No scala version specified")
|
||||
(organization, name, version, scalaVersion, Nil, mainClass, sbtVersion)
|
||||
}
|
||||
|
||||
val (extraParseErrors, extraModuleVersions) = coursier.util.Parse.moduleVersions(extra, scalaVersion)
|
||||
|
||||
if (extraParseErrors.nonEmpty) {
|
||||
???
|
||||
}
|
||||
|
||||
val extraDeps = extraModuleVersions.map {
|
||||
case (mod, ver) =>
|
||||
Dependency(mod, ver)
|
||||
}
|
||||
|
||||
val launcher = new Launcher(
|
||||
scalaVer0,
|
||||
// FIXME Add org & moduleName in this path
|
||||
new File(s"${sys.props("user.dir")}/target/sbt-components/components_scala$scalaVer0${if (sbtVersion0.isEmpty) "" else "_sbt" + sbtVersion0}"),
|
||||
new File(s"${sys.props("user.dir")}/target/ivy2")
|
||||
)
|
||||
|
||||
launcher.registerScalaComponents()
|
||||
|
||||
if (sbtVersion0.nonEmpty)
|
||||
launcher.registerSbtInterfaceComponents(sbtVersion0)
|
||||
|
||||
val appId = ApplicationID(
|
||||
org0,
|
||||
name0,
|
||||
ver0,
|
||||
mainClass0,
|
||||
mainComponents.toArray,
|
||||
crossVersioned = false,
|
||||
xsbti.CrossValue.Disabled,
|
||||
classpathExtra.map(new File(_)).toArray
|
||||
)
|
||||
|
||||
val appProvider = launcher.app(appId, extraDeps0 ++ extraDeps: _*)
|
||||
|
||||
val appMain = appProvider.newMain()
|
||||
|
||||
val appConfig = AppConfiguration(
|
||||
remainingArgs.toArray,
|
||||
new File(sys.props("user.dir")),
|
||||
appProvider
|
||||
)
|
||||
|
||||
val thread = Thread.currentThread()
|
||||
val previousLoader = thread.getContextClassLoader
|
||||
|
||||
val result =
|
||||
try {
|
||||
thread.setContextClassLoader(appProvider.loader())
|
||||
appMain.run(appConfig)
|
||||
} finally {
|
||||
thread.setContextClassLoader(previousLoader)
|
||||
}
|
||||
|
||||
result match {
|
||||
case _: xsbti.Continue =>
|
||||
case e: xsbti.Exit =>
|
||||
sys.exit(e.code())
|
||||
case _: xsbti.Reboot =>
|
||||
sys.error("Not able to reboot yet")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object Main extends AppOf[MainApp]
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package coursier.sbtlauncher
|
||||
|
||||
import java.net.URL
|
||||
|
||||
object Repository {
|
||||
|
||||
final case class Maven(id: String, url: URL) extends xsbti.MavenRepository
|
||||
|
||||
final case class Ivy(
|
||||
id: String,
|
||||
url: URL,
|
||||
ivyPattern: String,
|
||||
artifactPattern: String,
|
||||
mavenCompatible: Boolean,
|
||||
skipConsistencyCheck: Boolean,
|
||||
descriptorOptional: Boolean
|
||||
) extends xsbti.IvyRepository
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package coursier.sbtlauncher
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import coursier.Dependency
|
||||
import coursier.util.Parse
|
||||
|
||||
import scala.collection.JavaConverters._
|
||||
|
||||
final case class SbtConfig(
|
||||
organization: String,
|
||||
moduleName: String,
|
||||
version: String,
|
||||
scalaVersion: String,
|
||||
mainClass: String,
|
||||
dependencies: Seq[Dependency]
|
||||
)
|
||||
|
||||
object SbtConfig {
|
||||
|
||||
def defaultOrganization = "org.scala-sbt"
|
||||
def defaultModuleName = "sbt"
|
||||
def defaultMainClass = "sbt.xMain"
|
||||
|
||||
def fromConfig(config: Config): SbtConfig = {
|
||||
|
||||
val version = config.getString("sbt.version")
|
||||
|
||||
val scalaVersion =
|
||||
if (config.hasPath("scala.version"))
|
||||
config.getString("scala.version")
|
||||
else if (version.startsWith("0.13."))
|
||||
"2.10.6"
|
||||
else if (version.startsWith("1.0."))
|
||||
"2.12.1"
|
||||
else
|
||||
throw new Exception(s"Don't know what Scala version should be used for sbt version '$version'")
|
||||
|
||||
val org =
|
||||
if (config.hasPath("sbt.organization"))
|
||||
config.getString("sbt.organization")
|
||||
else
|
||||
defaultOrganization
|
||||
|
||||
val name =
|
||||
if (config.hasPath("sbt.module-name"))
|
||||
config.getString("sbt.module-name")
|
||||
else
|
||||
defaultModuleName
|
||||
|
||||
val mainClass =
|
||||
if (config.hasPath("sbt.main-class"))
|
||||
config.getString("sbt.main-class")
|
||||
else
|
||||
defaultMainClass
|
||||
|
||||
val scalaBinaryVersion = scalaVersion.split('.').take(2).mkString(".")
|
||||
val sbtBinaryVersion = version.split('.').take(2).mkString(".")
|
||||
|
||||
val rawPlugins =
|
||||
if (config.hasPath("plugins"))
|
||||
config.getStringList("plugins").asScala
|
||||
else
|
||||
Nil
|
||||
|
||||
val (pluginErrors, pluginsModuleVersions) = Parse.moduleVersions(rawPlugins, scalaVersion)
|
||||
|
||||
if (pluginErrors.nonEmpty) {
|
||||
???
|
||||
}
|
||||
|
||||
val pluginDependencies =
|
||||
pluginsModuleVersions.map {
|
||||
case (mod, ver) =>
|
||||
Dependency(
|
||||
mod.copy(
|
||||
attributes = mod.attributes ++ Seq(
|
||||
"scalaVersion" -> scalaBinaryVersion,
|
||||
"sbtVersion" -> sbtBinaryVersion
|
||||
)
|
||||
),
|
||||
ver
|
||||
)
|
||||
}
|
||||
|
||||
val rawDeps =
|
||||
if (config.hasPath("dependencies"))
|
||||
config.getStringList("dependencies").asScala
|
||||
else
|
||||
Nil
|
||||
|
||||
val (depsErrors, depsModuleVersions) = Parse.moduleVersions(rawDeps, scalaVersion)
|
||||
|
||||
if (depsErrors.nonEmpty) {
|
||||
???
|
||||
}
|
||||
|
||||
val dependencies =
|
||||
depsModuleVersions.map {
|
||||
case (mod, ver) =>
|
||||
Dependency(mod, ver)
|
||||
}
|
||||
|
||||
SbtConfig(
|
||||
org,
|
||||
name,
|
||||
version,
|
||||
scalaVersion,
|
||||
mainClass,
|
||||
pluginDependencies ++ dependencies
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package coursier.sbtlauncher
|
||||
|
||||
import java.io.File
|
||||
|
||||
final case class ScalaProvider(
|
||||
launcher: xsbti.Launcher,
|
||||
version: String,
|
||||
loader: ClassLoader,
|
||||
jars: Array[File],
|
||||
libraryJar: File,
|
||||
compilerJar: File,
|
||||
createApp: xsbti.ApplicationID => xsbti.AppProvider
|
||||
) extends xsbti.ScalaProvider {
|
||||
def app(id: xsbti.ApplicationID): xsbti.AppProvider =
|
||||
createApp(id)
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
sbt.version=0.13.8
|
||||
|
||||
plugins = [
|
||||
"io.get-coursier:sbt-coursier:1.0.0-M15-1"
|
||||
"org.xerial.sbt:sbt-pack:0.8.2"
|
||||
"org.scala-js:sbt-scalajs:0.6.14"
|
||||
"com.jsuereth:sbt-pgp:1.0.0"
|
||||
"org.scoverage:sbt-scoverage:1.4.0"
|
||||
"org.tpolecat:tut-plugin:0.4.8"
|
||||
"com.typesafe.sbt:sbt-proguard:0.2.2"
|
||||
"com.typesafe:sbt-mima-plugin:0.1.13"
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
"org.scala-sbt:scripted-plugin:"${sbt.version}
|
||||
]
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
COURSIER_VERSION=1.0.0-SNAPSHOT
|
||||
|
||||
"$(dirname "$0")/../coursier" bootstrap \
|
||||
"io.get-coursier:sbt-launcher_2.12:$COURSIER_VERSION" \
|
||||
-i launcher \
|
||||
-I launcher:org.scala-sbt:launcher-interface:1.0.0 \
|
||||
-o csbt \
|
||||
-J -Djline.shutdownhook=false
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
#!/usr/bin/env bash
|
||||
set -ev
|
||||
|
||||
SCALA_VERSION="${SCALA_VERSION:-${TRAVIS_SCALA_VERSION:-2.12.1}}"
|
||||
PULL_REQUEST="${PULL_REQUEST:-${TRAVIS_PULL_REQUEST:-false}}"
|
||||
BRANCH="${BRANCH:-${TRAVIS_BRANCH:-$(git rev-parse --abbrev-ref HEAD)}}"
|
||||
PUBLISH="${PUBLISH:-0}"
|
||||
SCALA_JS="${SCALA_JS:-0}"
|
||||
|
||||
JARJAR_VERSION="${JARJAR_VERSION:-1.0.1-coursier-SNAPSHOT}"
|
||||
|
||||
setupCoursierBinDir() {
|
||||
mkdir -p bin
|
||||
cp coursier bin/
|
||||
export PATH="$(pwd)/bin:$PATH"
|
||||
}
|
||||
|
||||
downloadInstallSbtExtras() {
|
||||
curl -L -o bin/sbt https://github.com/paulp/sbt-extras/raw/9ade5fa54914ca8aded44105bf4b9a60966f3ccd/sbt
|
||||
chmod +x bin/sbt
|
||||
}
|
||||
|
||||
integrationTestsRequirements() {
|
||||
# Required for ~/.ivy2/local repo tests
|
||||
sbt ++2.11.8 coreJVM/publishLocal http-server/publishLocal
|
||||
|
||||
# Required for HTTP authentication tests
|
||||
coursier launch \
|
||||
io.get-coursier:http-server-java7_2.11:1.0.0-SNAPSHOT \
|
||||
-r http://dl.bintray.com/scalaz/releases \
|
||||
-- \
|
||||
-d tests/jvm/src/test/resources/test-repo/http/abc.com \
|
||||
-u user -P pass -r realm \
|
||||
--list-pages \
|
||||
-v &
|
||||
}
|
||||
|
||||
setupCustomJarjar() {
|
||||
if [ ! -d "$HOME/.m2/repository/org/anarres/jarjar/jarjar-core/$JARJAR_VERSION" ]; then
|
||||
git clone https://github.com/alexarchambault/jarjar.git
|
||||
cd jarjar
|
||||
if ! grep -q "^version=$JARJAR_VERSION\$" gradle.properties; then
|
||||
echo "Expected jarjar version not found" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
git checkout 249c8dbb970f8
|
||||
./gradlew :jarjar-core:install
|
||||
cd ..
|
||||
rm -rf jarjar
|
||||
fi
|
||||
}
|
||||
|
||||
isScalaJs() {
|
||||
[ "$SCALA_JS" = 1 ]
|
||||
}
|
||||
|
||||
is210() {
|
||||
echo "$SCALA_VERSION" | grep -q "^2\.10"
|
||||
}
|
||||
|
||||
is211() {
|
||||
echo "$SCALA_VERSION" | grep -q "^2\.11"
|
||||
}
|
||||
|
||||
runSbtCoursierTests() {
|
||||
sbt ++$SCALA_VERSION coreJVM/publishLocal cache/publishLocal sbt-coursier/scripted
|
||||
}
|
||||
|
||||
runSbtShadingTests() {
|
||||
setupCustomJarjar
|
||||
sbt ++$SCALA_VERSION sbt-coursier/publishLocal sbt-shading/scripted
|
||||
}
|
||||
|
||||
jsCompile() {
|
||||
sbt ++$SCALA_VERSION js/compile js/test:compile coreJS/fastOptJS fetch-js/fastOptJS testsJS/test:fastOptJS js/test:fastOptJS
|
||||
}
|
||||
|
||||
jvmCompile() {
|
||||
sbt ++$SCALA_VERSION jvm/compile jvm/test:compile
|
||||
}
|
||||
|
||||
runJsTests() {
|
||||
sbt ++$SCALA_VERSION js/test
|
||||
}
|
||||
|
||||
runJvmTests() {
|
||||
sbt ++$SCALA_VERSION jvm/test jvm/it:test
|
||||
}
|
||||
|
||||
validateReadme() {
|
||||
sbt ++${SCALA_VERSION} tut
|
||||
}
|
||||
|
||||
checkBinaryCompatibility() {
|
||||
sbt ++${SCALA_VERSION} coreJVM/mimaReportBinaryIssues cache/mimaReportBinaryIssues
|
||||
}
|
||||
|
||||
testLauncherJava6() {
|
||||
sbt ++${SCALA_VERSION} cli/pack
|
||||
docker run -it --rm \
|
||||
-v $(pwd)/cli/target/pack:/opt/coursier \
|
||||
-e CI=true \
|
||||
openjdk:6-jre \
|
||||
/opt/coursier/bin/coursier fetch org.scalacheck::scalacheck:1.13.4
|
||||
|
||||
docker run -it --rm \
|
||||
-v $(pwd)/cli/target/pack:/opt/coursier \
|
||||
-e CI=true \
|
||||
openjdk:6-jre \
|
||||
/opt/coursier/bin/coursier launch --help
|
||||
}
|
||||
|
||||
testSbtCoursierJava6() {
|
||||
sbt ++${SCALA_VERSION} publishLocal
|
||||
git clone https://github.com/alexarchambault/scalacheck-shapeless.git
|
||||
cd scalacheck-shapeless
|
||||
cd project
|
||||
clean_plugin_sbt
|
||||
cd project
|
||||
clean_plugin_sbt
|
||||
cd ../..
|
||||
docker run -it --rm \
|
||||
-v $HOME/.ivy2/local:/root/.ivy2/local \
|
||||
-v $(pwd):/root/project \
|
||||
-v $(pwd)/../bin:/root/bin \
|
||||
-e CI=true \
|
||||
openjdk:6-jre \
|
||||
/bin/bash -c "cd /root/project && /root/bin/sbt update"
|
||||
cd ..
|
||||
}
|
||||
|
||||
clean_plugin_sbt() {
|
||||
mv plugins.sbt plugins.sbt0
|
||||
grep -v coursier plugins.sbt0 > plugins.sbt || true
|
||||
echo '
|
||||
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-SNAPSHOT")
|
||||
' >> plugins.sbt
|
||||
}
|
||||
|
||||
publish() {
|
||||
sbt ++${SCALA_VERSION} publish
|
||||
}
|
||||
|
||||
|
||||
# TODO Add coverage once https://github.com/scoverage/sbt-scoverage/issues/111 is fixed
|
||||
|
||||
setupCoursierBinDir
|
||||
downloadInstallSbtExtras
|
||||
|
||||
if isScalaJs; then
|
||||
jsCompile
|
||||
runJsTests
|
||||
else
|
||||
integrationTestsRequirements
|
||||
jvmCompile
|
||||
runJvmTests
|
||||
|
||||
if is210; then
|
||||
runSbtCoursierTests
|
||||
runSbtShadingTests
|
||||
fi
|
||||
|
||||
validateReadme
|
||||
checkBinaryCompatibility
|
||||
|
||||
# We're not using a jdk6 matrix entry with Travis here as some sources of coursier require Java 7 to compile
|
||||
# (even though it won't try to call Java 7 specific methods if it detects it runs under Java 6).
|
||||
# The tests here check that coursier is nonetheless fine when run under Java 6.
|
||||
|
||||
if is211; then
|
||||
testLauncherJava6
|
||||
fi
|
||||
|
||||
if is210; then
|
||||
testSbtCoursierJava6
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ "$PUBLISH" = 1 -a "$PULL_REQUEST" = false -a "$BRANCH" = master ]; then
|
||||
publish
|
||||
|
||||
if is211 && isScalaJs; then
|
||||
#"$(dirname "$0")/push-gh-pages.sh" "$SCALA_VERSION"
|
||||
:
|
||||
fi
|
||||
fi
|
||||
|
||||
Loading…
Reference in New Issue