mirror of https://github.com/sbt/sbt.git
Merge branch 'develop' into patch-1
This commit is contained in:
commit
10bfc4a5cf
|
|
@ -1,3 +1,7 @@
|
|||
sbt text eol=lf
|
||||
*.sh text eol=lf
|
||||
launcher-package/src/windows/sbt text eol=lf
|
||||
|
||||
# Exclude contraband generated files from diff (by default - you can see it if you want)
|
||||
**/contraband-scala/**/* -diff merge=ours
|
||||
**/contraband-scala/**/* linguist-generated=true
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ assignees: ''
|
|||
|
||||
---
|
||||
|
||||
Please use https://discuss.lightbend.com/c/tooling including a specific user story instead of posting them to the issue tracker.
|
||||
Please use https://github.com/sbt/sbt/discussions including a specific user story instead of posting them to the issue tracker.
|
||||
|
|
|
|||
|
|
@ -10,38 +10,48 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
java: "17.0-custom=tgz+https://download.java.net/java/GA/jdk17/0d483333a00540d886896bac774ff48b/35/GPL/openjdk-17_linux-x64_bin.tar.gz"
|
||||
java: 17
|
||||
distribution: temurin
|
||||
jobtype: 1
|
||||
- os: ubuntu-latest
|
||||
java: "17.0-custom=tgz+https://download.java.net/java/GA/jdk17/0d483333a00540d886896bac774ff48b/35/GPL/openjdk-17_linux-x64_bin.tar.gz"
|
||||
java: 17
|
||||
distribution: temurin
|
||||
jobtype: 2
|
||||
- os: ubuntu-latest
|
||||
java: "17.0-custom=tgz+https://download.java.net/java/GA/jdk17/0d483333a00540d886896bac774ff48b/35/GPL/openjdk-17_linux-x64_bin.tar.gz"
|
||||
java: 17
|
||||
distribution: temurin
|
||||
jobtype: 3
|
||||
- os: ubuntu-latest
|
||||
java: "17.0-custom=tgz+https://download.java.net/java/GA/jdk17/0d483333a00540d886896bac774ff48b/35/GPL/openjdk-17_linux-x64_bin.tar.gz"
|
||||
java: 17
|
||||
distribution: temurin
|
||||
jobtype: 4
|
||||
- os: ubuntu-latest
|
||||
java: "17-custom=tgz+https://download.java.net/java/GA/jdk17/0d483333a00540d886896bac774ff48b/35/GPL/openjdk-17_linux-x64_bin.tar.gz"
|
||||
java: 17
|
||||
distribution: temurin
|
||||
jobtype: 5
|
||||
- os: ubuntu-latest
|
||||
java: "adopt@1.8"
|
||||
java: 8
|
||||
distribution: adopt
|
||||
jobtype: 6
|
||||
- os: ubuntu-latest
|
||||
java: "adopt@1.8"
|
||||
java: 8
|
||||
distribution: adopt
|
||||
jobtype: 7
|
||||
- os: macos-latest
|
||||
java: "adopt@1.8"
|
||||
java: 8
|
||||
distribution: adopt
|
||||
jobtype: 8
|
||||
- os: windows-latest
|
||||
java: "adopt@1.8"
|
||||
java: 8
|
||||
distribution: adopt
|
||||
jobtype: 9
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
JAVA_OPTS: -Xms800M -Xmx2G -Xss6M -XX:ReservedCodeCacheSize=128M -server -Dsbt.io.virtual=false -Dfile.encoding=UTF-8
|
||||
JVM_OPTS: -Xms800M -Xmx2G -Xss6M -XX:ReservedCodeCacheSize=128M -server -Dsbt.io.virtual=false -Dfile.encoding=UTF-8
|
||||
SCALA_212: 2.12.15
|
||||
SCALA_213: 2.13.6
|
||||
SCALA_212: 2.12.16
|
||||
SCALA_213: 2.13.8
|
||||
SCALA_3: 3.1.0
|
||||
UTIL_TESTS: "utilCache/test utilControl/test utilInterface/test utilLogging/test utilPosition/test utilRelation/test utilScripted/test utilTracking/test"
|
||||
SBT_LOCAL: false
|
||||
TEST_SBT_VER: 1.5.0
|
||||
|
|
@ -50,119 +60,132 @@ jobs:
|
|||
SPARK_LOCAL_IP: "127.0.0.1"
|
||||
steps:
|
||||
- name: Checkout sbt/sbt
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Checkout sbt/io
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: sbt/io
|
||||
ref: develop
|
||||
path: io
|
||||
- name: Checkout sbt/librarymanagement
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: sbt/librarymanagement
|
||||
ref: develop
|
||||
path: librarymanagement
|
||||
- name: Checkout sbt/zinc
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: sbt/zinc
|
||||
ref: develop
|
||||
path: zinc
|
||||
- name: Setup
|
||||
uses: olafurpg/setup-scala@v13
|
||||
- name: Setup JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "${{ matrix.distribution }}"
|
||||
java-version: "${{ matrix.java }}"
|
||||
- name: Set up Python 3.7
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.7
|
||||
- name: Coursier cache
|
||||
uses: coursier/cache-action@v6
|
||||
- name: Cache sbt
|
||||
uses: actions/cache@v2.1.6
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.sbt
|
||||
key: ${{ runner.os }}-sbt-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }}
|
||||
- name: Build and test
|
||||
- name: Build and test (1)
|
||||
if: ${{ matrix.jobtype == 1 }}
|
||||
shell: bash
|
||||
run: |
|
||||
# ./sbt -v --client mimaReportBinaryIssues
|
||||
./sbt -v --client javafmtCheck
|
||||
./sbt -v --client "Test/javafmtCheck"
|
||||
./sbt -v --client scalafmtCheckAll
|
||||
./sbt -v --client scalafmtSbtCheck
|
||||
./sbt -v --client serverTestProj/scalafmtCheckAll
|
||||
./sbt -v --client headerCheck
|
||||
./sbt -v --client "Test/headerCheck"
|
||||
./sbt -v --client whitesourceOnPush
|
||||
./sbt -v --client "Test/compile"
|
||||
./sbt -v --client publishLocal
|
||||
./sbt -v --client test
|
||||
./sbt -v --client "serverTestProj/test"
|
||||
./sbt -v --client doc
|
||||
./sbt -v --client "all $UTIL_TESTS"
|
||||
./sbt -v --client ++$SCALA_213
|
||||
./sbt -v --client "all $UTIL_TESTS"
|
||||
- name: Build and test (2)
|
||||
if: ${{ matrix.jobtype == 2 }}
|
||||
shell: bash
|
||||
run: |
|
||||
./sbt -v "scripted actions/* apiinfo/* compiler-project/* ivy-deps-management/* reporter/* tests/* watch/* classloader-cache/* package/*"
|
||||
- name: Build and test (3)
|
||||
if: ${{ matrix.jobtype == 3 }}
|
||||
shell: bash
|
||||
run: |
|
||||
./sbt -v "dependencyTreeProj/publishLocal; scripted dependency-graph/* dependency-management/* plugins/* project-load/* java/* run/* nio/*"
|
||||
- name: Build and test (4)
|
||||
if: ${{ matrix.jobtype == 4 }}
|
||||
shell: bash
|
||||
run: |
|
||||
./sbt -v "repoOverrideTest:scripted dependency-management/*; scripted source-dependencies/* project/*"
|
||||
- name: Build and test (5)
|
||||
if: ${{ matrix.jobtype == 5 }}
|
||||
shell: bash
|
||||
run: |
|
||||
./sbt -v "++$SCALA_213!; test; ++$SCALA_3!; all utilControl/test utilRelation/test utilPosition/test"
|
||||
- name: Build and test (6)
|
||||
if: ${{ matrix.jobtype == 6 }}
|
||||
shell: bash
|
||||
run: |
|
||||
# build from fresh IO, LM, and Zinc
|
||||
BUILD_VERSION="1.5.0-SNAPSHOT"
|
||||
cd io
|
||||
sbt -v -Dsbt.build.version=${BUILD_VERSION} +publishLocal
|
||||
cd ../
|
||||
sbt -Dsbtlm.path=$HOME/work/sbt/sbt/librarymanagement -Dsbtzinc.path=$HOME/work/sbt/sbt/zinc -Dsbt.build.version=$BUILD_VERSION -Dsbt.build.fatal=false "+lowerUtils/publishLocal; {librarymanagement}/publishLocal; {zinc}/publishLocal; upperModules/publishLocal"
|
||||
rm -r $(find $HOME/.sbt/boot -name "*-SNAPSHOT") || true
|
||||
sbt -v -Dsbt.version=$BUILD_VERSION "++$SCALA_213; all $UTIL_TESTS; ++$SCALA_212; all $UTIL_TESTS; scripted actions/* source-dependencies/*1of3 dependency-management/*1of4 java/*"
|
||||
- name: Build and test (7)
|
||||
if: ${{ matrix.jobtype == 7 }}
|
||||
shell: bash
|
||||
run: |
|
||||
# test launcher script
|
||||
echo build using JDK 8 test using JDK 8 and JDK 11
|
||||
cd launcher-package
|
||||
sbt -Dsbt.build.version=$TEST_SBT_VER rpm:packageBin debian:packageBin
|
||||
sbt -Dsbt.build.version=$TEST_SBT_VER universal:packageBin universal:stage integrationTest/test
|
||||
cd citest && ./test.sh
|
||||
$HOME/bin/jabba install $JDK11 && exec $HOME/bin/jabba which --home $JDK11
|
||||
java -Xmx32m -version
|
||||
./test.sh
|
||||
- name: Build and test (8)
|
||||
if: ${{ matrix.jobtype == 8 }}
|
||||
shell: bash
|
||||
run: |
|
||||
# test launcher script
|
||||
echo build using JDK 8, test using JDK 8, on macOS
|
||||
cd launcher-package
|
||||
bin/coursier resolve
|
||||
sbt -Dsbt.build.version=$TEST_SBT_VER universal:packageBin universal:stage integrationTest/test
|
||||
cd citest && ./test.sh
|
||||
- name: Build and test (9)
|
||||
if: ${{ matrix.jobtype == 9 }}
|
||||
shell: bash
|
||||
run: |
|
||||
# test launcher script
|
||||
echo build using JDK 8, test using JDK 8, on Windows
|
||||
cd launcher-package
|
||||
bin/coursier.bat resolve
|
||||
sbt -Dsbt.build.version=$TEST_SBT_VER universal:packageBin universal:stage integrationTest/test
|
||||
cd citest
|
||||
./test.bat
|
||||
test3/test3.bat
|
||||
- name: Cleanup
|
||||
shell: bash
|
||||
run: |
|
||||
rm -rf "$HOME/.sbt/scripted/" || true
|
||||
case ${{ matrix.jobtype }} in
|
||||
1)
|
||||
./sbt -v --client mimaReportBinaryIssues
|
||||
./sbt -v --client javafmtCheck
|
||||
./sbt -v --client "Test/javafmtCheck"
|
||||
./sbt -v --client scalafmtCheckAll
|
||||
./sbt -v --client scalafmtSbtCheck
|
||||
./sbt -v --client serverTestProj/scalafmtCheckAll
|
||||
./sbt -v --client headerCheck
|
||||
./sbt -v --client "Test/headerCheck"
|
||||
./sbt -v --client whitesourceOnPush
|
||||
./sbt -v --client "Test/compile"
|
||||
./sbt -v --client publishLocal
|
||||
./sbt -v --client test
|
||||
./sbt -v --client "serverTestProj/test"
|
||||
./sbt -v --client doc
|
||||
./sbt -v --client "all $UTIL_TESTS"
|
||||
./sbt -v --client ++$SCALA_213
|
||||
./sbt -v --client "all $UTIL_TESTS"
|
||||
;;
|
||||
2)
|
||||
./sbt -v "scripted actions/* apiinfo/* compiler-project/* ivy-deps-management/* reporter/* tests/* watch/* classloader-cache/* package/*"
|
||||
;;
|
||||
3)
|
||||
./sbt -v "dependencyTreeProj/publishLocal; scripted dependency-graph/* dependency-management/* plugins/* project-load/* java/* run/* nio/*"
|
||||
;;
|
||||
4)
|
||||
./sbt -v "repoOverrideTest:scripted dependency-management/*; scripted source-dependencies/* project/*"
|
||||
;;
|
||||
5)
|
||||
./sbt -v "++$SCALA_213!; test;"
|
||||
;;
|
||||
6)
|
||||
# build from fresh IO, LM, and Zinc
|
||||
BUILD_VERSION="1.5.0-SNAPSHOT"
|
||||
cd io
|
||||
sbt -v -Dsbt.build.version=${BUILD_VERSION} +publishLocal
|
||||
cd ../
|
||||
sbt -Dsbtlm.path=$HOME/work/sbt/sbt/librarymanagement -Dsbtzinc.path=$HOME/work/sbt/sbt/zinc -Dsbt.build.version=$BUILD_VERSION -Dsbt.build.fatal=false "+lowerUtils/publishLocal; {librarymanagement}/publishLocal; {zinc}/publishLocal; upperModules/publishLocal"
|
||||
rm -r $(find $HOME/.sbt/boot -name "*-SNAPSHOT") || true
|
||||
sbt -v -Dsbt.version=$BUILD_VERSION "++$SCALA_213; all $UTIL_TESTS; ++$SCALA_212; all $UTIL_TESTS; scripted actions/* source-dependencies/*1of3 dependency-management/*1of4 java/*"
|
||||
;;
|
||||
7)
|
||||
# test launcher script
|
||||
echo build using JDK 8 test using JDK 8 and JDK 11
|
||||
cd launcher-package
|
||||
sbt -Dsbt.build.version=$TEST_SBT_VER rpm:packageBin debian:packageBin
|
||||
sbt -Dsbt.build.version=$TEST_SBT_VER universal:packageBin universal:stage integrationTest/test
|
||||
cd citest && ./test.sh
|
||||
$HOME/bin/jabba install $JDK11 && exec $HOME/bin/jabba which --home $JDK11
|
||||
java -Xmx32m -version
|
||||
./test.sh
|
||||
;;
|
||||
8)
|
||||
# test launcher script
|
||||
echo build using JDK 8, test using JDK 8, on macOS
|
||||
cd launcher-package
|
||||
bin/coursier resolve
|
||||
sbt -Dsbt.build.version=$TEST_SBT_VER universal:packageBin universal:stage integrationTest/test
|
||||
cd citest && ./test.sh
|
||||
;;
|
||||
9)
|
||||
# test launcher script
|
||||
echo build using JDK 8, test using JDK 8, on Windows
|
||||
cd launcher-package
|
||||
bin/coursier.bat resolve
|
||||
sbt -Dsbt.build.version=$TEST_SBT_VER universal:packageBin universal:stage integrationTest/test
|
||||
cd citest
|
||||
./test.bat
|
||||
test3/test3.bat
|
||||
;;
|
||||
*)
|
||||
echo unknown jobtype
|
||||
exit 1
|
||||
esac
|
||||
rm -rf "$HOME/.sbt/scripted/" || true
|
||||
rm -rf "$HOME/.ivy2/local" || true
|
||||
rm -r $(find $HOME/.sbt/boot -name "*-SNAPSHOT") || true
|
||||
|
|
|
|||
|
|
@ -16,21 +16,21 @@ jobs:
|
|||
JAVA_OPTS: -Xms800M -Xmx800M -Xss6M -XX:ReservedCodeCacheSize=128M -server -Dsbt.io.virtual=false -Dfile.encoding=UTF-8
|
||||
steps:
|
||||
- name: Checkout sbt/sbt
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Checkout sbt/io
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: sbt/io
|
||||
ref: develop
|
||||
path: io
|
||||
- name: Checkout sbt/librarymanagement
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: sbt/librarymanagement
|
||||
ref: develop
|
||||
path: librarymanagement
|
||||
- name: Checkout sbt/zinc
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: sbt/zinc
|
||||
ref: develop
|
||||
|
|
|
|||
|
|
@ -11,5 +11,6 @@ npm-debug.log
|
|||
.bloop
|
||||
.metals
|
||||
.bsp/
|
||||
.vscode/
|
||||
metals.sbt
|
||||
launcher-package/citest/freshly-baked
|
||||
|
|
|
|||
|
|
@ -21,3 +21,8 @@ align.openParenDefnSite = false
|
|||
danglingParentheses = true
|
||||
|
||||
trailingCommas = preserve
|
||||
|
||||
# TODO update scalafmt and enable Scala 3
|
||||
project.excludeFilters = [
|
||||
"internal/util-position/src/main/scala-3/sbt/internal/util/SourcePositionMacro.scala"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -151,14 +151,14 @@ suite with `sbt testOnly`
|
|||
|
||||
#### Integration tests
|
||||
|
||||
Scripted integration tests reside in `sbt/src/sbt-test` and are
|
||||
Scripted integration tests reside in `sbt-app/src/sbt-test` and are
|
||||
written using the same testing infrastructure sbt plugin authors can
|
||||
use to test their own plugins with sbt. You can read more about this
|
||||
style of tests [here](https://www.scala-sbt.org/1.0/docs/Testing-sbt-plugins).
|
||||
|
||||
You can run the integration tests with the `sbt scripted` sbt
|
||||
command. To run a single test, such as the test in
|
||||
`sbt/src/sbt-test/project/global-plugin`, simply run:
|
||||
`sbt-app/src/sbt-test/project/global-plugin`, simply run:
|
||||
|
||||
sbt "scripted project/global-plugin"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
[](https://travis-ci.com/github/sbt/sbt)
|
||||
[](https://github.com/sbt/sbt/actions/workflows/ci.yml)
|
||||
[](https://index.scala-lang.org/sbt/sbt)
|
||||
[](https://gitter.im/sbt/sbt)
|
||||
|
||||
|
|
|
|||
36
build.sbt
36
build.sbt
|
|
@ -10,7 +10,7 @@ import scala.util.Try
|
|||
// ThisBuild settings take lower precedence,
|
||||
// but can be shared across the multi projects.
|
||||
ThisBuild / version := {
|
||||
val v = "1.6.0-SNAPSHOT"
|
||||
val v = "1.7.0-SNAPSHOT"
|
||||
nightlyVersion.getOrElse(v)
|
||||
}
|
||||
ThisBuild / version2_13 := "2.0.0-SNAPSHOT"
|
||||
|
|
@ -46,7 +46,7 @@ ThisBuild / resolvers += Resolver.mavenLocal
|
|||
|
||||
Global / semanticdbEnabled := !(Global / insideCI).value
|
||||
// Change main/src/main/scala/sbt/plugins/SemanticdbPlugin.scala too, if you change this.
|
||||
Global / semanticdbVersion := "4.4.28"
|
||||
Global / semanticdbVersion := "4.5.9"
|
||||
val excludeLint = SettingKey[Set[Def.KeyedInitialize[_]]]("excludeLintKeys")
|
||||
Global / excludeLint := (Global / excludeLint).?.value.getOrElse(Set.empty)
|
||||
Global / excludeLint += componentID
|
||||
|
|
@ -68,10 +68,6 @@ def commonBaseSettings: Seq[Setting[_]] = Def.settings(
|
|||
componentID := None,
|
||||
resolvers += Resolver.typesafeIvyRepo("releases").withName("typesafe-sbt-build-ivy-releases"),
|
||||
resolvers += Resolver.sonatypeRepo("snapshots"),
|
||||
resolvers += Resolver.url(
|
||||
"bintray-scala-hedgehog",
|
||||
url("https://dl.bintray.com/hedgehogqa/scala-hedgehog")
|
||||
)(Resolver.ivyStylePatterns),
|
||||
testFrameworks += TestFramework("hedgehog.sbt.Framework"),
|
||||
testFrameworks += TestFramework("verify.runner.Framework"),
|
||||
Global / concurrentRestrictions += Util.testExclusiveRestriction,
|
||||
|
|
@ -106,8 +102,15 @@ def commonBaseSettings: Seq[Setting[_]] = Def.settings(
|
|||
run / fork := true,
|
||||
)
|
||||
def commonSettings: Seq[Setting[_]] =
|
||||
commonBaseSettings :+
|
||||
addCompilerPlugin(kindProjector)
|
||||
commonBaseSettings :+ {
|
||||
libraryDependencies ++= {
|
||||
if (scalaBinaryVersion.value == "3") {
|
||||
Nil
|
||||
} else {
|
||||
Seq(compilerPlugin(kindProjector))
|
||||
}
|
||||
}
|
||||
}
|
||||
def utilCommonSettings: Seq[Setting[_]] =
|
||||
baseSettings :+ (crossScalaVersions := (scala212 :: scala213 :: Nil))
|
||||
|
||||
|
|
@ -467,7 +470,7 @@ lazy val utilScripted = (project in file("internal") / "util-scripted")
|
|||
.settings(
|
||||
utilCommonSettings,
|
||||
name := "Util Scripted",
|
||||
libraryDependencies += scalaParsers,
|
||||
libraryDependencies += scalaParsers.value,
|
||||
utilMimaSettings,
|
||||
)
|
||||
.configure(addSbtIO)
|
||||
|
|
@ -481,7 +484,7 @@ lazy val testingProj = (project in file("testing"))
|
|||
baseSettings,
|
||||
name := "Testing",
|
||||
libraryDependencies ++= Seq(
|
||||
scalaXml,
|
||||
scalaXml.value,
|
||||
testInterface,
|
||||
launcherInterface,
|
||||
sjsonNewScalaJson.value
|
||||
|
|
@ -807,7 +810,13 @@ lazy val coreMacrosProj = (project in file("core-macros"))
|
|||
.settings(
|
||||
baseSettings :+ (crossScalaVersions := (scala212 :: scala213 :: Nil)),
|
||||
name := "Core Macros",
|
||||
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value,
|
||||
libraryDependencies += {
|
||||
if (scalaBinaryVersion.value == "3") {
|
||||
"org.scala-lang" % "scala-compiler" % scala213
|
||||
} else {
|
||||
"org.scala-lang" % "scala-compiler" % scalaVersion.value
|
||||
}
|
||||
},
|
||||
SettingKey[Boolean]("exportPipelining") := false,
|
||||
mimaSettings,
|
||||
)
|
||||
|
|
@ -917,7 +926,7 @@ lazy val mainProj = (project in file("main"))
|
|||
}
|
||||
},
|
||||
libraryDependencies ++=
|
||||
(Seq(scalaXml, launcherInterface, caffeine, lmCoursierShaded) ++ log4jModules),
|
||||
(Seq(scalaXml.value, launcherInterface, caffeine, lmCoursierShaded) ++ log4jModules),
|
||||
libraryDependencies ++= (scalaVersion.value match {
|
||||
case v if v.startsWith("2.12.") => List()
|
||||
case _ => List(scalaPar)
|
||||
|
|
@ -1048,6 +1057,7 @@ lazy val mainProj = (project in file("main"))
|
|||
exclude[DirectMissingMethodProblem]("sbt.Defaults.earlyArtifactPathSetting"),
|
||||
exclude[MissingClassProblem]("sbt.internal.server.BuildServerReporter$"),
|
||||
exclude[IncompatibleTemplateDefProblem]("sbt.internal.server.BuildServerReporter"),
|
||||
exclude[MissingClassProblem]("sbt.internal.CustomHttp*"),
|
||||
)
|
||||
)
|
||||
.configure(
|
||||
|
|
@ -1108,7 +1118,7 @@ lazy val serverTestProj = (project in file("server-test"))
|
|||
val rawClasspath =
|
||||
(Compile / fullClasspathAsJars).value.map(_.data).mkString(java.io.File.pathSeparator)
|
||||
val cp =
|
||||
if (scala.util.Properties.isWin) rawClasspath.replaceAllLiterally("\\", "\\\\")
|
||||
if (scala.util.Properties.isWin) rawClasspath.replace("\\", "\\\\")
|
||||
else rawClasspath
|
||||
val content = {
|
||||
s"""|
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ final case class HCons[H, T <: HList](head: H, tail: T) extends HList {
|
|||
type Wrap[M[_]] = M[H] :+: T#Wrap[M]
|
||||
def :+:[G](g: G): G :+: H :+: T = HCons(g, this)
|
||||
|
||||
override def toString = head + " :+: " + tail.toString
|
||||
override def toString = head.toString + " :+: " + tail.toString
|
||||
}
|
||||
|
||||
object HList {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ private final class Settings0[ScopeType](
|
|||
(data get scope).flatMap(_ get key)
|
||||
|
||||
def set[T](scope: ScopeType, key: AttributeKey[T], value: T): Settings[ScopeType] = {
|
||||
val map = data getOrElse (scope, AttributeMap.empty)
|
||||
val map = data.getOrElse(scope, AttributeMap.empty)
|
||||
val newData = data.updated(scope, map.put(key, value))
|
||||
new Settings0(newData, delegates)
|
||||
}
|
||||
|
|
@ -476,7 +476,7 @@ trait Init[ScopeType] {
|
|||
if (posDefined.size == settings.size) "defined at:"
|
||||
else
|
||||
"some of the defining occurrences:"
|
||||
header + (posDefined.distinct mkString ("\n\t", "\n\t", "\n"))
|
||||
header + (posDefined.distinct.mkString("\n\t", "\n\t", "\n"))
|
||||
} else ""
|
||||
}
|
||||
|
||||
|
|
@ -711,10 +711,10 @@ trait Init[ScopeType] {
|
|||
def mapReferenced(g: MapScoped): Setting[T] = make(key, init mapReferenced g, pos)
|
||||
|
||||
def validateReferenced(g: ValidateRef): Either[Seq[Undefined], Setting[T]] =
|
||||
(init validateReferenced g).right.map(newI => make(key, newI, pos))
|
||||
(init validateReferenced g).map(newI => make(key, newI, pos))
|
||||
|
||||
private[sbt] def validateKeyReferenced(g: ValidateKeyRef): Either[Seq[Undefined], Setting[T]] =
|
||||
(init validateKeyReferenced g).right.map(newI => make(key, newI, pos))
|
||||
(init validateKeyReferenced g).map(newI => make(key, newI, pos))
|
||||
|
||||
def mapKey(g: MapScoped): Setting[T] = make(g(key), init, pos)
|
||||
def mapInit(f: (ScopedKey[T], T) => T): Setting[T] = make(key, init(t => f(key, t)), pos)
|
||||
|
|
@ -879,9 +879,8 @@ trait Init[ScopeType] {
|
|||
def evaluate(ss: Settings[ScopeType]): T = f(in evaluate ss) evaluate ss
|
||||
def mapReferenced(g: MapScoped) = new Bind[S, T](s => f(s) mapReferenced g, in mapReferenced g)
|
||||
|
||||
def validateKeyReferenced(g: ValidateKeyRef) = (in validateKeyReferenced g).right.map {
|
||||
validIn =>
|
||||
new Bind[S, T](s => handleUndefined(f(s) validateKeyReferenced g), validIn)
|
||||
def validateKeyReferenced(g: ValidateKeyRef) = (in validateKeyReferenced g).map { validIn =>
|
||||
new Bind[S, T](s => handleUndefined(f(s) validateKeyReferenced g), validIn)
|
||||
}
|
||||
|
||||
def mapConstant(g: MapConstant) = new Bind[S, T](s => f(s) mapConstant g, in mapConstant g)
|
||||
|
|
@ -898,7 +897,7 @@ trait Init[ScopeType] {
|
|||
|
||||
def validateKeyReferenced(g: ValidateKeyRef) = a match {
|
||||
case None => Right(this)
|
||||
case Some(i) => Right(new Optional(i.validateKeyReferenced(g).right.toOption, f))
|
||||
case Some(i) => Right(new Optional(i.validateKeyReferenced(g).toOption, f))
|
||||
}
|
||||
|
||||
def mapConstant(g: MapConstant): Initialize[T] = new Optional(a map mapConstantT(g).fn, f)
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ object Util {
|
|||
def camelToHyphen(s: String): String =
|
||||
Camel.replaceAllIn(s, m => m.group(1) + "-" + m.group(2).toLowerCase(Locale.ENGLISH))
|
||||
|
||||
def quoteIfKeyword(s: String): String = if (ScalaKeywords.values(s)) '`' + s + '`' else s
|
||||
def quoteIfKeyword(s: String): String = if (ScalaKeywords.values(s)) s"`${s}`" else s
|
||||
|
||||
def ignoreResult[T](f: => T): Unit = macro Macro.ignore
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ object Util {
|
|||
System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("windows")
|
||||
|
||||
lazy val isCygwin: Boolean = {
|
||||
val os = Option(System.getenv("OSTYPE"))
|
||||
val os = sys.env.get("OSTYPE")
|
||||
os match {
|
||||
case Some(x) => x.toLowerCase(Locale.ENGLISH).contains("cygwin")
|
||||
case _ => false
|
||||
|
|
@ -64,7 +64,7 @@ object Util {
|
|||
lazy val isNonCygwinWindows: Boolean = isWindows && !isCygwin
|
||||
lazy val isCygwinWindows: Boolean = isWindows && isCygwin
|
||||
|
||||
lazy val isEmacs: Boolean = Option(System.getenv("INSIDE_EMACS")).isDefined
|
||||
lazy val isEmacs: Boolean = sys.env.contains("INSIDE_EMACS")
|
||||
|
||||
def nil[A]: List[A] = List.empty[A]
|
||||
def nilSeq[A]: Seq[A] = Seq.empty[A]
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package sbt.internal.util
|
||||
|
||||
import org.scalatest._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
abstract class UnitSpec extends FlatSpec with Matchers
|
||||
abstract class UnitSpec extends AnyFlatSpec with Matchers
|
||||
|
|
|
|||
|
|
@ -178,13 +178,7 @@ abstract class JLine extends LineReader {
|
|||
protected[this] lazy val in: InputStream = Terminal.wrappedSystemIn
|
||||
|
||||
override def readLine(prompt: String, mask: Option[Char] = None): Option[String] =
|
||||
try {
|
||||
unsynchronizedReadLine(prompt, mask)
|
||||
} catch {
|
||||
case _: InterruptedException =>
|
||||
// println("readLine: InterruptedException")
|
||||
Option("")
|
||||
}
|
||||
unsynchronizedReadLine(prompt, mask)
|
||||
|
||||
private[this] def unsynchronizedReadLine(prompt: String, mask: Option[Char]): Option[String] =
|
||||
readLineWithHistory(prompt, mask) map { x =>
|
||||
|
|
|
|||
|
|
@ -909,7 +909,7 @@ private final class StringLiteral(str: String, start: Int) extends ValidParser[S
|
|||
if (str.charAt(start) == c) stringLiteral(str, start + 1) else new Invalid(resultEmpty)
|
||||
|
||||
def completions(level: Int) = Completions.single(Completion.suggestion(str.substring(start)))
|
||||
override def toString = '"' + str + '"'
|
||||
override def toString = "\"" + str + "\""
|
||||
}
|
||||
|
||||
private final class CharacterClass(f: Char => Boolean, label: String) extends ValidParser[Char] {
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ trait Parsers {
|
|||
* Parses a potentially quoted String value. The value may be verbatim quoted ([[StringVerbatim]]),
|
||||
* quoted with interpreted escapes ([[StringEscapable]]), or unquoted ([[NotQuoted]]).
|
||||
*/
|
||||
lazy val StringBasic = StringVerbatim | StringEscapable | NotQuoted
|
||||
lazy val StringBasic = StringVerbatim | StringEscapable | NotQuoted | NotQuotedThenQuoted
|
||||
|
||||
/**
|
||||
* Parses a verbatim quoted String value, discarding the quotes in the result. This kind of quoted text starts with triple quotes `"""`
|
||||
|
|
@ -238,12 +238,12 @@ trait Parsers {
|
|||
val notDelim = charClass(c => c != open && c != close).*.string
|
||||
def impl(): Parser[String] = {
|
||||
(open ~ (notDelim ~ close).?).flatMap {
|
||||
case (l, Some((content, r))) => Parser.success(l + content + r)
|
||||
case (l, Some((content, r))) => Parser.success(s"$l$content$r")
|
||||
case (l, None) =>
|
||||
((notDelim ~ impl()).map {
|
||||
case (leftPrefix, nestedBraces) => leftPrefix + nestedBraces
|
||||
}.+ ~ notDelim ~ close).map {
|
||||
case ((nested, suffix), r) => l + nested.mkString + suffix + r
|
||||
case ((nested, suffix), r) => s"$l${nested.mkString}$suffix$r"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -270,6 +270,11 @@ trait Parsers {
|
|||
/** Parses an unquoted, non-empty String value that cannot start with a double quote and cannot contain whitespace.*/
|
||||
lazy val NotQuoted = (NotDQuoteSpaceClass ~ OptNotSpace) map { case (c, s) => c.toString + s }
|
||||
|
||||
/** Parses a non-empty String value that cannot start with a double quote, but includes double quotes.*/
|
||||
lazy val NotQuotedThenQuoted = (NotQuoted ~ StringEscapable) map {
|
||||
case (s1, s2) => s"""$s1\"$s2\""""
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies `rep` zero or more times, separated by `sep`.
|
||||
* The result is the (possibly empty) sequence of results from the multiple `rep` applications. The `sep` results are discarded.
|
||||
|
|
|
|||
|
|
@ -119,6 +119,8 @@ object ParserTest extends Properties("Completing Parser") {
|
|||
property("repeatDep requires at least one token") = !matches(repeat, "")
|
||||
property("repeatDep accepts one token") = matches(repeat, colors.toSeq.head)
|
||||
property("repeatDep accepts two tokens") = matches(repeat, colors.toSeq.take(2).mkString(" "))
|
||||
property("parses string that doesn't start with quotes, but includes quotes within it") =
|
||||
matches(StringBasic, "-Dsilicon:z3ConfigArgs=\"model=true model_validate=true\"")
|
||||
}
|
||||
object ParserExample {
|
||||
val ws = charClass(_.isWhitespace, "whitespace").+
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package sbt.internal.util
|
||||
|
||||
import org.scalatest._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
abstract class UnitSpec extends FlatSpec with Matchers
|
||||
abstract class UnitSpec extends AnyFlatSpec with Matchers
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
package sbt.internal.util.complete
|
||||
|
||||
import org.scalatest.FlatSpec
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
|
||||
class SizeParserSpec extends FlatSpec {
|
||||
class SizeParserSpec extends AnyFlatSpec {
|
||||
"SizeParser" should "handle raw bytes" in {
|
||||
assert(Parser.parse(str = "123456", SizeParser.value) == Right(123456L))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package xsbti;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A DiagnosticCode is a unique identifier that the compiler can associate with a diagnostic. This
|
||||
* is useful for tools to be able to quickly identify what diagnostic is being reported without
|
||||
* having to rely on parsing the actual diagnostic message, which might not be stable.
|
||||
*/
|
||||
public interface DiagnosticCode {
|
||||
/** The unique code. This is typically in the format of E000 */
|
||||
String code();
|
||||
|
||||
/** Possible explanation to explain the meaning of the code */
|
||||
Optional<String> explanation();
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package xsbti;
|
||||
|
||||
/**
|
||||
* Related information for a given diagnostic. At times this can be another place in your code
|
||||
* contributing to the diagnostic or just relevant code relating to the diagnostic.
|
||||
*/
|
||||
public interface DiagnosticRelatedInformation {
|
||||
/** Position of the related information */
|
||||
Position position();
|
||||
|
||||
/** Message indicating why this related information is attached to the diagnostic. */
|
||||
String message();
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
package xsbti;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface Problem {
|
||||
|
|
@ -26,4 +28,24 @@ public interface Problem {
|
|||
default Optional<String> rendered() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* The unique code attached to the diagnostic being reported.
|
||||
*
|
||||
* <p>NOTE: To avoid breaking compatibility we provide a default to account for older Scala
|
||||
* versions that do not have codes.
|
||||
*/
|
||||
default Optional<DiagnosticCode> diagnosticCode() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* The possible releated information for the diagnostic being reported.
|
||||
*
|
||||
* <p>NOTE: To avoid breaking compatibility we provide a default to account for older Scala
|
||||
* versions that do not have the concept of "related information".
|
||||
*/
|
||||
default List<DiagnosticRelatedInformation> diagnosticRelatedInforamation() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ object GlobalLogging {
|
|||
): GlobalLogging = {
|
||||
val loggerName = generateName
|
||||
val log = LoggerContext.globalContext.logger(loggerName, None, None)
|
||||
val appender = ConsoleAppender(ConsoleAppender.generateName, console)
|
||||
val appender = ConsoleAppender(ConsoleAppender.generateName(), console)
|
||||
LoggerContext.globalContext.addAppender(loggerName, appender -> Level.Info)
|
||||
GlobalLogging(log, console, appender, GlobalLogBacking(newBackingFile), newAppender)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,15 +67,15 @@ object MainAppender {
|
|||
)
|
||||
|
||||
def defaultScreen(console: ConsoleOut): Appender =
|
||||
ConsoleAppender(ConsoleAppender.generateName, console)
|
||||
ConsoleAppender(ConsoleAppender.generateName(), console)
|
||||
|
||||
def defaultScreen(
|
||||
console: ConsoleOut,
|
||||
suppressedMessage: SuppressedTraceContext => Option[String]
|
||||
): Appender = {
|
||||
ConsoleAppender(
|
||||
ConsoleAppender.generateName,
|
||||
Terminal.get,
|
||||
ConsoleAppender.generateName(),
|
||||
console,
|
||||
suppressedMessage = suppressedMessage
|
||||
)
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ object MainAppender {
|
|||
def defaultBacked(loggerName: String, useFormat: Boolean): PrintWriter => Appender =
|
||||
to => {
|
||||
ConsoleAppender(
|
||||
ConsoleAppender.generateName,
|
||||
ConsoleAppender.generateName(),
|
||||
ConsoleOut.printWriterOut(to),
|
||||
useFormat = useFormat
|
||||
)
|
||||
|
|
@ -50,13 +50,6 @@ class ManagedLogger(
|
|||
}
|
||||
}
|
||||
|
||||
@deprecated("Use macro-powered StringTypeTag.fast instead", "1.4.0")
|
||||
def registerStringCodec[A](
|
||||
s: ShowLines[A],
|
||||
tt: scala.reflect.runtime.universe.TypeTag[A]
|
||||
): Unit = {
|
||||
LogExchange.registerStringCodec[A](s, tt)
|
||||
}
|
||||
def registerStringCodec[A: ShowLines: StringTypeTag]: Unit = {
|
||||
LogExchange.registerStringCodec[A]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@ private[sbt] final class ProgressState(
|
|||
addBytes(terminal, bytes)
|
||||
val toWrite = new ArrayBuffer[Byte]
|
||||
terminal.prompt match {
|
||||
case a: Prompt.AskUser if a.render.nonEmpty && canClearPrompt => toWrite ++= cleanPrompt
|
||||
case _ =>
|
||||
case a: Prompt.AskUser if a.render().nonEmpty && canClearPrompt => toWrite ++= cleanPrompt
|
||||
case _ =>
|
||||
}
|
||||
val endsWithNewLine = bytes.endsWith(lineSeparatorBytes)
|
||||
if (endsWithNewLine || bytes.containsSlice(lineSeparatorBytes)) {
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ object Terminal {
|
|||
}
|
||||
private[sbt] lazy val isAnsiSupported: Boolean = logFormatEnabled.getOrElse(useColorDefault)
|
||||
|
||||
private[this] val isDumb = "dumb" == System.getenv("TERM")
|
||||
private[this] val isDumb = Some("dumb") == sys.env.get("TERM")
|
||||
private[this] def isDumbTerminal = isDumb || System.getProperty("jline.terminal", "") == "none"
|
||||
private[this] val hasConsole = Option(java.lang.System.console).isDefined
|
||||
private[this] def useColorDefault: Boolean = {
|
||||
|
|
@ -736,22 +736,20 @@ object Terminal {
|
|||
val supershell: Boolean
|
||||
)
|
||||
private[sbt] val TERMINAL_PROPS = "SBT_TERMINAL_PROPS"
|
||||
private val props = System.getenv(TERMINAL_PROPS) match {
|
||||
case null => None
|
||||
case p =>
|
||||
p.split(",") match {
|
||||
case Array(width, height, ansi, color, supershell) =>
|
||||
Try(
|
||||
new Props(
|
||||
width.toInt,
|
||||
height.toInt,
|
||||
ansi.toBoolean,
|
||||
color.toBoolean,
|
||||
supershell.toBoolean
|
||||
)
|
||||
).toOption
|
||||
case _ => None
|
||||
}
|
||||
private val props = sys.env.get(TERMINAL_PROPS) flatMap { p =>
|
||||
p.split(",") match {
|
||||
case Array(width, height, ansi, color, supershell) =>
|
||||
Try(
|
||||
new Props(
|
||||
width.toInt,
|
||||
height.toInt,
|
||||
ansi.toBoolean,
|
||||
color.toBoolean,
|
||||
supershell.toBoolean
|
||||
)
|
||||
).toOption
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
private[sbt] def startedByRemoteClient = props.isDefined
|
||||
|
||||
|
|
@ -905,7 +903,7 @@ object Terminal {
|
|||
new AtomicReference[((Int, Int), Deadline)](((1, 1), Deadline.now - 1.day))
|
||||
private[this] def setSize() = size.set((Try(getSizeImpl).getOrElse((1, 1)), Deadline.now))
|
||||
private[this] def getSize = size.get match {
|
||||
case (s, d) if (d + sizeRefreshPeriod).isOverdue =>
|
||||
case (s, d) if (d + sizeRefreshPeriod).isOverdue() =>
|
||||
setSize()
|
||||
size.get._1
|
||||
case (s, _) => s
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ private[util] class WindowsInputStream(term: org.jline.terminal.Terminal, in: In
|
|||
private val SHIFT_PRESSED = 0x0010;
|
||||
private def getCapability(cap: Capability): String = term.getStringCapability(cap) match {
|
||||
case null => null
|
||||
case c => c.replaceAllLiterally("\\E", "\u001B")
|
||||
case c => c.replace("\\E", "\u001B")
|
||||
}
|
||||
/*
|
||||
* This function is a hybrid of jline 2 WindowsTerminal.readConsoleInput
|
||||
|
|
|
|||
|
|
@ -7,15 +7,14 @@
|
|||
|
||||
package sbt.util
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import org.apache.logging.log4j.{ LogManager => XLogManager, Level => XLevel }
|
||||
import org.apache.logging.log4j.core.{ Appender => XAppender, LoggerContext => XLoggerContext }
|
||||
import org.apache.logging.log4j.core.config.{ AppenderRef, LoggerConfig }
|
||||
import org.apache.logging.log4j.core.config.LoggerConfig
|
||||
import org.apache.logging.log4j.core.layout.PatternLayout
|
||||
import org.apache.logging.log4j.core.{ LoggerContext => XLoggerContext }
|
||||
import org.apache.logging.log4j.{ LogManager => XLogManager }
|
||||
import sbt.internal.util._
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import scala.collection.concurrent
|
||||
import sjsonnew.JsonFormat
|
||||
import org.apache.logging.log4j.core.appender.AsyncAppender
|
||||
|
||||
// http://logging.apache.org/log4j/2.x/manual/customconfig.html
|
||||
// https://logging.apache.org/log4j/2.x/log4j-core/apidocs/index.html
|
||||
|
|
@ -29,54 +28,18 @@ sealed abstract class LogExchange {
|
|||
Util.ignoreResult(configs.putIfAbsent(name, config))
|
||||
private[util] def removeConfig(name: String): Option[LoggerConfig] = Option(configs.remove(name))
|
||||
|
||||
@deprecated("Use LoggerContext to create loggers", "1.4.0")
|
||||
def logger(name: String): ManagedLogger = logger(name, None, None)
|
||||
@deprecated("Use LoggerContext to create loggers", "1.4.0")
|
||||
def logger(name: String, channelName: Option[String], execId: Option[String]): ManagedLogger =
|
||||
LoggerContext.globalContext.logger(name, channelName, execId)
|
||||
@deprecated("Use LoggerContext to unbind appenders", "1.4.0")
|
||||
def unbindLoggerAppenders(loggerName: String): Unit = {
|
||||
LoggerContext.globalContext.clearAppenders(loggerName)
|
||||
}
|
||||
@deprecated("Use LoggerContext to bind appenders", "1.4.0")
|
||||
def bindLoggerAppenders(
|
||||
loggerName: String,
|
||||
appenders: List[(XAppender, Level.Value)]
|
||||
): Unit = {
|
||||
appenders.foreach {
|
||||
case (a, l) =>
|
||||
LoggerContext.globalContext
|
||||
.addAppender(loggerName, new ConsoleAppenderFromLog4J(loggerName, a) -> l)
|
||||
}
|
||||
}
|
||||
@deprecated("Use LoggerContext to bind appenders", "1.4.0")
|
||||
def bindLoggerAppenders(
|
||||
loggerName: String,
|
||||
appenders: Seq[(Appender, Level.Value)]
|
||||
): Unit = bindLoggerAppenders(loggerName, appenders.map { case (a, l) => a.toLog4J -> l }.toList)
|
||||
@deprecated("unused", "1.4.0")
|
||||
def loggerConfig(loggerName: String): LoggerConfig = configs.get(loggerName)
|
||||
|
||||
@deprecated("unused", "1.4.0")
|
||||
lazy val asyncStdout = buildAsyncStdout
|
||||
@deprecated("unused", "1.4.0")
|
||||
private[sbt] def buildAsyncStdout: AsyncAppender = {
|
||||
val ctx = XLogManager.getContext(false) match { case x: XLoggerContext => x }
|
||||
val config = ctx.getConfiguration
|
||||
val appender = ConsoleAppender("Stdout").toLog4J
|
||||
// CustomConsoleAppender.createAppender("Stdout", layout, null, null)
|
||||
appender.start
|
||||
config.addAppender(appender)
|
||||
val asyncAppender: AsyncAppender = AsyncAppender
|
||||
.newBuilder()
|
||||
.setName("AsyncStdout")
|
||||
.setAppenderRefs(Array(AppenderRef.createAppenderRef("Stdout", XLevel.DEBUG, null)))
|
||||
.setBlocking(false)
|
||||
.setConfiguration(config)
|
||||
.build
|
||||
asyncAppender.start
|
||||
config.addAppender(asyncAppender)
|
||||
asyncAppender
|
||||
): Unit = {
|
||||
appenders.map(LoggerContext.globalContext.addAppender(loggerName, _))
|
||||
()
|
||||
}
|
||||
|
||||
// Construct these StringTypeTags manually, because they're used at the very startup of sbt
|
||||
|
|
@ -87,9 +50,9 @@ sealed abstract class LogExchange {
|
|||
lazy val stringTypeTagSuccessEvent = StringTypeTag[SuccessEvent]("sbt.internal.util.SuccessEvent")
|
||||
|
||||
private[sbt] def initStringCodecs(): Unit = {
|
||||
import sbt.internal.util.codec.SuccessEventShowLines._
|
||||
import sbt.internal.util.codec.ThrowableShowLines._
|
||||
import sbt.internal.util.codec.TraceEventShowLines._
|
||||
import sbt.internal.util.codec.SuccessEventShowLines._
|
||||
|
||||
registerStringCodecByStringTypeTag(stringTypeTagThrowable)
|
||||
registerStringCodecByStringTypeTag(stringTypeTagTraceEvent)
|
||||
|
|
@ -111,15 +74,6 @@ sealed abstract class LogExchange {
|
|||
lo
|
||||
}
|
||||
|
||||
@deprecated("It is now necessary to provide a json format instance", "1.4.0")
|
||||
def jsonCodec[A](tag: String): Option[JsonFormat[A]] = None
|
||||
@deprecated("Always returns false", "1.4.0")
|
||||
def hasJsonCodec(tag: String): Boolean = false
|
||||
@deprecated("This is a no-op", "1.4.0")
|
||||
def getOrElseUpdateJsonCodec[A](tag: String, v: JsonFormat[A]): JsonFormat[A] = v
|
||||
@deprecated("The log manager no longer caches jsonCodecs", "1.4.0")
|
||||
def jsonCodecs(): concurrent.Map[String, JsonFormat[_]] = concurrent.TrieMap.empty
|
||||
|
||||
def stringCodec[A](tag: String): Option[ShowLines[A]] =
|
||||
stringCodecs.get(tag) map { _.asInstanceOf[ShowLines[A]] }
|
||||
def hasStringCodec(tag: String): Boolean =
|
||||
|
|
@ -127,13 +81,6 @@ sealed abstract class LogExchange {
|
|||
def getOrElseUpdateStringCodec[A](tag: String, v: ShowLines[A]): ShowLines[A] =
|
||||
stringCodecs.getOrElseUpdate(tag, v).asInstanceOf[ShowLines[A]]
|
||||
|
||||
@deprecated("Prefer macro based registerStringCodec", "1.4.0")
|
||||
def registerStringCodec[A](
|
||||
st: ShowLines[A],
|
||||
tt: scala.reflect.runtime.universe.TypeTag[A]
|
||||
): Unit = {
|
||||
registerStringCodecByStringTypeTag(StringTypeTag.apply[A](tt))(st)
|
||||
}
|
||||
private[sbt] def registerStringCodec[A: ShowLines: StringTypeTag]: Unit = {
|
||||
registerStringCodecByStringTypeTag(implicitly[StringTypeTag[A]])
|
||||
}
|
||||
|
|
@ -144,8 +91,8 @@ sealed abstract class LogExchange {
|
|||
}
|
||||
|
||||
private[sbt] def init(): XLoggerContext = {
|
||||
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory
|
||||
import org.apache.logging.log4j.core.config.Configurator
|
||||
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory
|
||||
val builder = ConfigurationBuilderFactory.newConfigurationBuilder
|
||||
builder.setConfigurationName("sbt.util.logging")
|
||||
val ctx = Configurator.initialize(builder.build())
|
||||
|
|
|
|||
|
|
@ -7,15 +7,11 @@
|
|||
|
||||
package sbt.util
|
||||
|
||||
import sbt.internal.util._
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import org.apache.logging.log4j.{ Level => XLevel }
|
||||
import org.apache.logging.log4j.core.{ Appender => XAppender, LoggerContext => XLoggerContext }
|
||||
import org.apache.logging.log4j.core.config.{ AppenderRef, LoggerConfig }
|
||||
import sbt.internal.util._
|
||||
import scala.collection.JavaConverters._
|
||||
import org.apache.logging.log4j.core.config.AbstractConfiguration
|
||||
import org.apache.logging.log4j.message.ObjectMessage
|
||||
|
||||
/**
|
||||
* Provides a context for generating loggers during task evaluation. The logger context
|
||||
|
|
@ -35,83 +31,8 @@ sealed trait LoggerContext extends AutoCloseable {
|
|||
def remove(name: String): Unit
|
||||
}
|
||||
object LoggerContext {
|
||||
private[this] val useLog4J = System.getProperty("sbt.log.uselog4j", "false") == "true"
|
||||
private[this] lazy val global = new LoggerContext.LoggerContextImpl
|
||||
private[this] lazy val globalLog4J = new LoggerContext.Log4JLoggerContext(LogExchange.context)
|
||||
private[sbt] lazy val globalContext = if (useLog4J) globalLog4J else global
|
||||
private[util] class Log4JLoggerContext(val xlc: XLoggerContext) extends LoggerContext {
|
||||
private val config = xlc.getConfiguration match {
|
||||
case a: AbstractConfiguration => a
|
||||
case _ => throw new IllegalStateException("")
|
||||
}
|
||||
val loggers = new java.util.Vector[String]
|
||||
private[this] val closed = new AtomicBoolean(false)
|
||||
override def logger(
|
||||
name: String,
|
||||
channelName: Option[String],
|
||||
execId: Option[String]
|
||||
): ManagedLogger = {
|
||||
if (closed.get) {
|
||||
throw new IllegalStateException("Tried to create logger for closed LoggerContext")
|
||||
}
|
||||
val loggerConfig = LoggerConfig.createLogger(
|
||||
false,
|
||||
XLevel.DEBUG,
|
||||
name,
|
||||
// disable the calculation of caller location as it is very expensive
|
||||
// https://issues.apache.org/jira/browse/LOG4J2-153
|
||||
"false",
|
||||
Array[AppenderRef](),
|
||||
null,
|
||||
config,
|
||||
null
|
||||
)
|
||||
config.addLogger(name, loggerConfig)
|
||||
val logger = xlc.getLogger(name)
|
||||
LogExchange.addConfig(name, loggerConfig)
|
||||
loggers.add(name)
|
||||
val xlogger = new MiniLogger {
|
||||
def log(level: Level.Value, message: => String): Unit =
|
||||
logger.log(
|
||||
ConsoleAppender.toXLevel(level),
|
||||
new ObjectMessage(StringEvent(level.toString, message, channelName, execId))
|
||||
)
|
||||
def log[T](level: Level.Value, message: ObjectEvent[T]): Unit =
|
||||
logger.log(ConsoleAppender.toXLevel(level), new ObjectMessage(message))
|
||||
}
|
||||
new ManagedLogger(name, channelName, execId, xlogger, Some(Terminal.get), this)
|
||||
}
|
||||
override def clearAppenders(loggerName: String): Unit = {
|
||||
val lc = config.getLoggerConfig(loggerName)
|
||||
lc.getAppenders.asScala foreach {
|
||||
case (name, a) =>
|
||||
a.stop()
|
||||
lc.removeAppender(name)
|
||||
}
|
||||
}
|
||||
override def addAppender(
|
||||
loggerName: String,
|
||||
appender: (Appender, Level.Value)
|
||||
): Unit = {
|
||||
val lc = config.getLoggerConfig(loggerName)
|
||||
appender match {
|
||||
case (x: XAppender, lv) => lc.addAppender(x, ConsoleAppender.toXLevel(lv), null)
|
||||
case (x, lv) => lc.addAppender(x.toLog4J, ConsoleAppender.toXLevel(lv), null)
|
||||
}
|
||||
}
|
||||
override def appenders(loggerName: String): Seq[Appender] = {
|
||||
val lc = config.getLoggerConfig(loggerName)
|
||||
lc.getAppenders.asScala.collect { case (name, ca: ConsoleAppender) => ca }.toVector
|
||||
}
|
||||
override def remove(name: String): Unit = {
|
||||
val lc = config.getLoggerConfig(name)
|
||||
config.removeLogger(name)
|
||||
}
|
||||
def close(): Unit = if (closed.compareAndSet(false, true)) {
|
||||
loggers.forEach(l => remove(l))
|
||||
loggers.clear()
|
||||
}
|
||||
}
|
||||
private[sbt] lazy val globalContext: LoggerContext = new LoggerContext.LoggerContextImpl
|
||||
|
||||
private[util] class LoggerContextImpl extends LoggerContext {
|
||||
private class Log extends MiniLogger {
|
||||
private val consoleAppenders: java.util.Vector[(Appender, Level.Value)] =
|
||||
|
|
@ -186,6 +107,5 @@ object LoggerContext {
|
|||
loggers.clear()
|
||||
}
|
||||
}
|
||||
private[sbt] def apply(useLog4J: Boolean) =
|
||||
if (useLog4J) new Log4JLoggerContext(LogExchange.context) else new LoggerContextImpl
|
||||
private[sbt] def apply() = new LoggerContextImpl
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ object Escapes extends Properties("Escapes") {
|
|||
)
|
||||
}
|
||||
assert(isEscapeTerminator(terminator))
|
||||
def makeString: String = ESC + content + terminator
|
||||
def makeString: String = s"$ESC$content$terminator"
|
||||
|
||||
override def toString =
|
||||
if (content.isEmpty) s"ESC (${terminator.toInt})"
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@ package sbt.util
|
|||
|
||||
import sbt.internal.util._
|
||||
|
||||
import org.scalatest._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
class LogExchangeSpec extends FlatSpec with Matchers {
|
||||
class LogExchangeSpec extends AnyFlatSpec with Matchers {
|
||||
import LogExchange._
|
||||
|
||||
checkTypeTag("stringTypeTagThrowable", stringTypeTagThrowable, StringTypeTag.fast[Throwable])
|
||||
|
|
|
|||
|
|
@ -7,16 +7,18 @@
|
|||
|
||||
package sbt.internal.util
|
||||
|
||||
import org.scalatest._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import sbt.util._
|
||||
import java.io.{ File, PrintWriter }
|
||||
import sbt.io.Using
|
||||
import scala.annotation.nowarn
|
||||
|
||||
class ManagedLoggerSpec extends FlatSpec with Matchers {
|
||||
val context = LoggerContext(useLog4J = true)
|
||||
class ManagedLoggerSpec extends AnyFlatSpec with Matchers {
|
||||
val context = LoggerContext()
|
||||
@nowarn
|
||||
val asyncStdout = new ConsoleAppenderFromLog4J("asyncStdout", LogExchange.asyncStdout)
|
||||
//TODO create a new appender for testing purposes - 3/12/21
|
||||
val asyncStdout = ConsoleAppender("asyncStdout")
|
||||
def newLogger(name: String): ManagedLogger = context.logger(name, None, None)
|
||||
"ManagedLogger" should "log to console" in {
|
||||
val log = newLogger("foo")
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
package sbt.internal.util
|
||||
|
||||
import org.scalatest.FlatSpec
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
|
||||
class CleanStringSpec extends FlatSpec {
|
||||
class CleanStringSpec extends AnyFlatSpec {
|
||||
"EscHelpers" should "not modify normal strings" in {
|
||||
val cleanString = s"1234"
|
||||
assert(EscHelpers.stripColorsAndMoves(cleanString) == cleanString)
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@ package sbt.internal.util
|
|||
|
||||
import java.io.{ File, PrintStream }
|
||||
|
||||
import org.scalatest.{ BeforeAndAfterAll, FlatSpec }
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.BeforeAndAfterAll
|
||||
import sbt.internal.util.Terminal.SimpleTerminal
|
||||
|
||||
import scala.io.Source
|
||||
|
||||
class ProgressStateSpec extends FlatSpec with BeforeAndAfterAll {
|
||||
class ProgressStateSpec extends AnyFlatSpec with BeforeAndAfterAll {
|
||||
|
||||
private lazy val fileIn = new File("/tmp/tmp.txt")
|
||||
private lazy val fileOut = Source.fromFile("/tmp/tmp.txt")
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ package sbt.internal.util
|
|||
|
||||
import java.io.InputStream
|
||||
import java.nio.charset.Charset
|
||||
import org.scalatest.FlatSpec
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import java.util.concurrent.LinkedBlockingQueue
|
||||
|
||||
class UTF8DecoderSpec extends FlatSpec {
|
||||
class UTF8DecoderSpec extends AnyFlatSpec {
|
||||
val decoder = Charset.forName("UTF-8").newDecoder
|
||||
"ascii characters" should "not be modified" in {
|
||||
val inputStream = new InputStream {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt.internal.util
|
||||
|
||||
import scala.language.experimental.macros
|
||||
import scala.annotation.tailrec
|
||||
import scala.reflect.macros.blackbox
|
||||
import scala.reflect.internal.util.UndefinedPosition
|
||||
|
||||
abstract class SourcePositionImpl {
|
||||
|
||||
/** Creates a SourcePosition by using the enclosing position of the invocation of this method.
|
||||
* @return SourcePosition
|
||||
*/
|
||||
def fromEnclosing(): SourcePosition = macro SourcePositionMacro.fromEnclosingImpl
|
||||
}
|
||||
|
||||
final class SourcePositionMacro(val c: blackbox.Context) {
|
||||
import c.universe.{ NoPosition => _, _ }
|
||||
|
||||
def fromEnclosingImpl(): Expr[SourcePosition] = {
|
||||
val pos = c.enclosingPosition
|
||||
if (!pos.isInstanceOf[UndefinedPosition] && pos.line >= 0 && pos.source != null) {
|
||||
val f = pos.source.file
|
||||
val name = constant[String](ownerSource(f.path, f.name))
|
||||
val line = constant[Int](pos.line)
|
||||
reify { LinePosition(name.splice, line.splice) }
|
||||
} else
|
||||
reify { NoPosition }
|
||||
}
|
||||
|
||||
private[this] def ownerSource(path: String, name: String): String = {
|
||||
@tailrec def inEmptyPackage(s: Symbol): Boolean =
|
||||
s != NoSymbol && (
|
||||
s.owner == c.mirror.EmptyPackage
|
||||
|| s.owner == c.mirror.EmptyPackageClass
|
||||
|| inEmptyPackage(s.owner)
|
||||
)
|
||||
|
||||
c.internal.enclosingOwner match {
|
||||
case ec if !ec.isStatic => name
|
||||
case ec if inEmptyPackage(ec) => path
|
||||
case ec => s"(${ec.fullName}) $name"
|
||||
}
|
||||
}
|
||||
|
||||
private[this] def constant[T: WeakTypeTag](t: T): Expr[T] = c.Expr[T](Literal(Constant(t)))
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt.internal.util
|
||||
|
||||
import scala.quoted.{ Expr, Quotes, quotes }
|
||||
|
||||
abstract class SourcePositionImpl {
|
||||
|
||||
/** Creates a SourcePosition by using the enclosing position of the invocation of this method.
|
||||
*
|
||||
* @return SourcePosition
|
||||
*/
|
||||
inline def fromEnclosing(): SourcePosition =
|
||||
${ SourcePositionImpl.fromEnclosingImpl }
|
||||
}
|
||||
|
||||
object SourcePositionImpl {
|
||||
|
||||
def fromEnclosingImpl(using Quotes): Expr[SourcePosition] = {
|
||||
val x = quotes.reflect.Position.ofMacroExpansion
|
||||
|
||||
'{
|
||||
LinePosition(
|
||||
path = ${Expr(x.sourceFile.name)},
|
||||
startLine = ${Expr(x.startLine + 1)}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
package sbt.internal.util
|
||||
|
||||
import scala.language.experimental.macros
|
||||
|
||||
sealed trait SourcePosition
|
||||
|
||||
sealed trait FilePosition extends SourcePosition {
|
||||
|
|
@ -28,47 +26,4 @@ final case class RangePosition(path: String, range: LineRange) extends FilePosit
|
|||
def startLine = range.start
|
||||
}
|
||||
|
||||
object SourcePosition {
|
||||
|
||||
/** Creates a SourcePosition by using the enclosing position of the invocation of this method.
|
||||
* @return SourcePosition
|
||||
*/
|
||||
def fromEnclosing(): SourcePosition = macro SourcePositionMacro.fromEnclosingImpl
|
||||
|
||||
}
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.reflect.macros.blackbox
|
||||
import scala.reflect.internal.util.UndefinedPosition
|
||||
|
||||
final class SourcePositionMacro(val c: blackbox.Context) {
|
||||
import c.universe.{ NoPosition => _, _ }
|
||||
|
||||
def fromEnclosingImpl(): Expr[SourcePosition] = {
|
||||
val pos = c.enclosingPosition
|
||||
if (!pos.isInstanceOf[UndefinedPosition] && pos.line >= 0 && pos.source != null) {
|
||||
val f = pos.source.file
|
||||
val name = constant[String](ownerSource(f.path, f.name))
|
||||
val line = constant[Int](pos.line)
|
||||
reify { LinePosition(name.splice, line.splice) }
|
||||
} else
|
||||
reify { NoPosition }
|
||||
}
|
||||
|
||||
private[this] def ownerSource(path: String, name: String): String = {
|
||||
@tailrec def inEmptyPackage(s: Symbol): Boolean =
|
||||
s != NoSymbol && (
|
||||
s.owner == c.mirror.EmptyPackage
|
||||
|| s.owner == c.mirror.EmptyPackageClass
|
||||
|| inEmptyPackage(s.owner)
|
||||
)
|
||||
|
||||
c.internal.enclosingOwner match {
|
||||
case ec if !ec.isStatic => name
|
||||
case ec if inEmptyPackage(ec) => path
|
||||
case ec => s"(${ec.fullName}) $name"
|
||||
}
|
||||
}
|
||||
|
||||
private[this] def constant[T: WeakTypeTag](t: T): Expr[T] = c.Expr[T](Literal(Constant(t)))
|
||||
}
|
||||
object SourcePosition extends SourcePositionImpl
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
package sbt.internal.util
|
||||
|
||||
import org.scalatest._
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
|
||||
class SourcePositionSpec extends FlatSpec {
|
||||
class SourcePositionSpec extends AnyFlatSpec {
|
||||
"SourcePosition()" should "return a sane SourcePosition" in {
|
||||
val filename = "SourcePositionSpec.scala"
|
||||
val lineNumber = 16
|
||||
|
|
|
|||
|
|
@ -214,5 +214,5 @@ private final class MRelation[A, B](fwd: Map[A, Set[B]], rev: Map[B, Set[A]])
|
|||
override def hashCode = fwd.filterNot(_._2.isEmpty).hashCode()
|
||||
|
||||
override def toString =
|
||||
all.map { case (a, b) => a + " -> " + b }.mkString("Relation [", ", ", "]")
|
||||
all.map { case (a, b) => s"$a -> $b" }.mkString("Relation [", ", ", "]")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import java.io.File
|
|||
import sbt.io.{ IO, Path }
|
||||
import sbt.io.syntax._
|
||||
import Path._
|
||||
import sbt.io.IO
|
||||
|
||||
class FileCommands(baseDirectory: File) extends BasicStatementHandler {
|
||||
lazy val commands = commandMap
|
||||
|
|
@ -25,7 +24,7 @@ class FileCommands(baseDirectory: File) extends BasicStatementHandler {
|
|||
"mkdir" nonEmpty makeDirectories _,
|
||||
"absent" nonEmpty absent _,
|
||||
// "sync" twoArg("Two directory paths", sync _),
|
||||
"newer" twoArg ("Two paths", newer _),
|
||||
"newer".twoArg("Two paths", newer _),
|
||||
"pause" noArg {
|
||||
println("Pausing in " + baseDirectory)
|
||||
/*readLine("Press enter to continue. ") */
|
||||
|
|
@ -33,11 +32,11 @@ class FileCommands(baseDirectory: File) extends BasicStatementHandler {
|
|||
System.console.readLine
|
||||
println()
|
||||
},
|
||||
"sleep" oneArg ("Time in milliseconds", time => Thread.sleep(time.toLong)),
|
||||
"sleep".oneArg("Time in milliseconds", time => Thread.sleep(time.toLong)),
|
||||
"exec" nonEmpty (execute _),
|
||||
"copy" copy (to => rebase(baseDirectory, to)),
|
||||
"copy-file" twoArg ("Two paths", copyFile _),
|
||||
"must-mirror" twoArg ("Two paths", diffFiles _),
|
||||
"copy-file".twoArg("Two paths", copyFile _),
|
||||
"must-mirror".twoArg("Two paths", diffFiles _),
|
||||
"copy-flat" copy flat
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,7 @@ object ScriptedRunnerImpl {
|
|||
tests: Array[String],
|
||||
handlersProvider: HandlersProvider
|
||||
): Unit = {
|
||||
val context =
|
||||
LoggerContext(useLog4J = System.getProperty("sbt.log.uselog4j", "false") == "true")
|
||||
val context = LoggerContext()
|
||||
val runner = new ScriptedTests(resourceBaseDirectory, bufferLog, handlersProvider)
|
||||
val logger = newLogger(context)
|
||||
val allTests = get(tests, resourceBaseDirectory, logger) flatMap {
|
||||
|
|
@ -103,7 +102,7 @@ final class ScriptedTests(
|
|||
log: ManagedLogger,
|
||||
context: LoggerContext,
|
||||
): Seq[() => Option[String]] = {
|
||||
for (groupDir <- (resourceBaseDirectory * group).get; nme <- (groupDir * name).get) yield {
|
||||
for (groupDir <- (resourceBaseDirectory * group).get(); nme <- (groupDir * name).get()) yield {
|
||||
val g = groupDir.getName
|
||||
val n = nme.getName
|
||||
val str = s"$g / $n"
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ val root = (project in file(".")).
|
|||
},
|
||||
// Used to have "openjdk-8-jdk" but that doesn't work on Ubuntu 14.04 https://github.com/sbt/sbt/issues/3105
|
||||
// before that we had java6-runtime-headless" and that was pulling in JDK9 on Ubuntu 16.04 https://github.com/sbt/sbt/issues/2931
|
||||
debianPackageDependencies in Debian ++= Seq("bash (>= 3.2)"),
|
||||
debianPackageDependencies in Debian ++= Seq("bash (>= 3.2)", "curl | wget"),
|
||||
debianPackageRecommends in Debian += "git",
|
||||
linuxPackageMappings in Debian += {
|
||||
val bd = sourceDirectory.value
|
||||
|
|
@ -273,7 +273,7 @@ val root = (project in file(".")).
|
|||
case (k, BinSbt) =>
|
||||
import java.nio.file.{Files, FileSystems}
|
||||
val x = IO.read(k)
|
||||
IO.write(t / "sbt", x.replaceAllLiterally(
|
||||
IO.write(t / "sbt", x.replace(
|
||||
"declare init_sbt_version=_to_be_replaced",
|
||||
s"declare init_sbt_version=$sbtVersionToRelease"))
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import minitest._
|
|||
import java.io.File
|
||||
|
||||
object SbtScriptTest extends SimpleTestSuite with PowerAssertions {
|
||||
lazy val isWindows: Boolean = sys.props("os.name").toLowerCase(java.util.Locale.ENGLISH).contains("windows")
|
||||
lazy val isWindows: Boolean =
|
||||
sys.props("os.name").toLowerCase(java.util.Locale.ENGLISH).contains("windows")
|
||||
lazy val sbtScript =
|
||||
if (isWindows) new File("target/universal/stage/bin/sbt.bat")
|
||||
else new File("target/universal/stage/bin/sbt")
|
||||
|
|
@ -12,12 +13,13 @@ object SbtScriptTest extends SimpleTestSuite with PowerAssertions {
|
|||
private val javaBinDir = new File("integration-test", "bin").getAbsolutePath
|
||||
|
||||
private def makeTest(
|
||||
name: String,
|
||||
javaOpts: String = "",
|
||||
sbtOpts: String = "",
|
||||
name: String,
|
||||
javaOpts: String = "",
|
||||
sbtOpts: String = "",
|
||||
)(args: String*)(f: List[String] => Any) = {
|
||||
test(name) {
|
||||
val out = sbtProcessWithOpts(args: _*)(javaOpts = javaOpts, sbtOpts = sbtOpts).!!.linesIterator.toList
|
||||
val out =
|
||||
sbtProcessWithOpts(args: _*)(javaOpts = javaOpts, sbtOpts = sbtOpts).!!.linesIterator.toList
|
||||
f(out)
|
||||
()
|
||||
}
|
||||
|
|
@ -26,12 +28,14 @@ object SbtScriptTest extends SimpleTestSuite with PowerAssertions {
|
|||
def sbtProcess(args: String*) = sbtProcessWithOpts(args: _*)("", "")
|
||||
def sbtProcessWithOpts(args: String*)(javaOpts: String, sbtOpts: String) = {
|
||||
val path = sys.env("PATH")
|
||||
sbt.internal.Process(Seq(sbtScript.getAbsolutePath) ++ args, new File("citest"),
|
||||
sbt.internal.Process(
|
||||
Seq(sbtScript.getAbsolutePath) ++ args,
|
||||
new File("citest"),
|
||||
"JAVA_OPTS" -> javaOpts,
|
||||
"SBT_OPTS" -> sbtOpts,
|
||||
if (isWindows)
|
||||
"JAVACMD" -> new File(javaBinDir, "java.cmd").getAbsolutePath()
|
||||
else
|
||||
else
|
||||
"PATH" -> (javaBinDir + File.pathSeparator + path)
|
||||
)
|
||||
}
|
||||
|
|
@ -48,9 +52,14 @@ object SbtScriptTest extends SimpleTestSuite with PowerAssertions {
|
|||
assert(out.contains[String]("-Dsbt.color=false"))
|
||||
}
|
||||
|
||||
makeTest("sbt --no-colors in SBT_OPTS", sbtOpts = "--no-colors")("compile", "-v") { out: List[String] =>
|
||||
if (isWindows) cancel("Test not supported on windows")
|
||||
assert(out.contains[String]("-Dsbt.log.noformat=true"))
|
||||
makeTest("sbt --no-colors in SBT_OPTS", sbtOpts = "--no-colors")("compile", "-v") {
|
||||
out: List[String] =>
|
||||
if (isWindows) cancel("Test not supported on windows")
|
||||
assert(out.contains[String]("-Dsbt.log.noformat=true"))
|
||||
}
|
||||
|
||||
makeTest("sbt --no-server")("compile", "--no-server", "-v") { out: List[String] =>
|
||||
assert(out.contains[String]("-Dsbt.server.autostart=false"))
|
||||
}
|
||||
|
||||
makeTest("sbt --debug-inc")("compile", "--debug-inc", "-v") { out: List[String] =>
|
||||
|
|
@ -77,33 +86,43 @@ object SbtScriptTest extends SimpleTestSuite with PowerAssertions {
|
|||
assert(out.contains[String]("-Xmx503m"))
|
||||
}
|
||||
|
||||
makeTest("sbt with -mem 503, -Xmx in JAVA_OPTS", javaOpts = "-Xmx1024m")("-mem", "503", "-v") { out: List[String] =>
|
||||
assert(out.contains[String]("-Xmx503m"))
|
||||
assert(!out.contains[String]("-Xmx1024m"))
|
||||
makeTest("sbt with -mem 503, -Xmx in JAVA_OPTS", javaOpts = "-Xmx1024m")("-mem", "503", "-v") {
|
||||
out: List[String] =>
|
||||
assert(out.contains[String]("-Xmx503m"))
|
||||
assert(!out.contains[String]("-Xmx1024m"))
|
||||
}
|
||||
|
||||
makeTest("sbt with -mem 503, -Xmx in SBT_OPTS", sbtOpts = "-Xmx1024m")("-mem", "503", "-v") { out: List[String] =>
|
||||
assert(out.contains[String]("-Xmx503m"))
|
||||
assert(!out.contains[String]("-Xmx1024m"))
|
||||
makeTest("sbt with -mem 503, -Xmx in SBT_OPTS", sbtOpts = "-Xmx1024m")("-mem", "503", "-v") {
|
||||
out: List[String] =>
|
||||
assert(out.contains[String]("-Xmx503m"))
|
||||
assert(!out.contains[String]("-Xmx1024m"))
|
||||
}
|
||||
|
||||
makeTest("sbt with -mem 503, -Xss in JAVA_OPTS", javaOpts = "-Xss6m")("-mem", "503", "-v") { out: List[String] =>
|
||||
assert(out.contains[String]("-Xmx503m"))
|
||||
assert(!out.contains[String]("-Xss6m"))
|
||||
makeTest("sbt with -mem 503, -Xss in JAVA_OPTS", javaOpts = "-Xss6m")("-mem", "503", "-v") {
|
||||
out: List[String] =>
|
||||
assert(out.contains[String]("-Xmx503m"))
|
||||
assert(!out.contains[String]("-Xss6m"))
|
||||
}
|
||||
|
||||
makeTest("sbt with -mem 503, -Xss in SBT_OPTS", sbtOpts = "-Xss6m")("-mem", "503", "-v") { out: List[String] =>
|
||||
assert(out.contains[String]("-Xmx503m"))
|
||||
assert(!out.contains[String]("-Xss6m"))
|
||||
makeTest("sbt with -mem 503, -Xss in SBT_OPTS", sbtOpts = "-Xss6m")("-mem", "503", "-v") {
|
||||
out: List[String] =>
|
||||
assert(out.contains[String]("-Xmx503m"))
|
||||
assert(!out.contains[String]("-Xss6m"))
|
||||
}
|
||||
|
||||
makeTest("sbt with -Xms2048M -Xmx2048M -Xss6M in JAVA_OPTS", javaOpts = "-Xms2048M -Xmx2048M -Xss6M")("-v") { out: List[String] =>
|
||||
makeTest(
|
||||
"sbt with -Xms2048M -Xmx2048M -Xss6M in JAVA_OPTS",
|
||||
javaOpts = "-Xms2048M -Xmx2048M -Xss6M"
|
||||
)("-v") { out: List[String] =>
|
||||
assert(out.contains[String]("-Xms2048M"))
|
||||
assert(out.contains[String]("-Xmx2048M"))
|
||||
assert(out.contains[String]("-Xss6M"))
|
||||
}
|
||||
|
||||
makeTest("sbt with -Xms2048M -Xmx2048M -Xss6M in SBT_OPTS", sbtOpts = "-Xms2048M -Xmx2048M -Xss6M")( "-v") { out: List[String] =>
|
||||
makeTest(
|
||||
"sbt with -Xms2048M -Xmx2048M -Xss6M in SBT_OPTS",
|
||||
sbtOpts = "-Xms2048M -Xmx2048M -Xss6M"
|
||||
)("-v") { out: List[String] =>
|
||||
assert(out.contains[String]("-Xms2048M"))
|
||||
assert(out.contains[String]("-Xmx2048M"))
|
||||
assert(out.contains[String]("-Xss6M"))
|
||||
|
|
@ -125,13 +144,18 @@ object SbtScriptTest extends SimpleTestSuite with PowerAssertions {
|
|||
assert(out.contains[String]("-XX:PermSize=128M"))
|
||||
}
|
||||
|
||||
makeTest("sbt with -XX:+UseG1GC -XX:+PrintGC in JAVA_OPTS", javaOpts = "-XX:+UseG1GC -XX:+PrintGC")("-v") { out: List[String] =>
|
||||
makeTest(
|
||||
"sbt with -XX:+UseG1GC -XX:+PrintGC in JAVA_OPTS",
|
||||
javaOpts = "-XX:+UseG1GC -XX:+PrintGC"
|
||||
)("-v") { out: List[String] =>
|
||||
assert(out.contains[String]("-XX:+UseG1GC"))
|
||||
assert(out.contains[String]("-XX:+PrintGC"))
|
||||
assert(!out.contains[String]("-XX:+UseG1GC=-XX:+PrintGC"))
|
||||
}
|
||||
|
||||
makeTest("sbt with -XX:-UseG1GC -XX:-PrintGC in SBT_OPTS", sbtOpts = "-XX:+UseG1GC -XX:+PrintGC")( "-v") { out: List[String] =>
|
||||
makeTest("sbt with -XX:-UseG1GC -XX:-PrintGC in SBT_OPTS", sbtOpts = "-XX:+UseG1GC -XX:+PrintGC")(
|
||||
"-v"
|
||||
) { out: List[String] =>
|
||||
assert(out.contains[String]("-XX:+UseG1GC"))
|
||||
assert(out.contains[String]("-XX:+PrintGC"))
|
||||
assert(!out.contains[String]("-XX:+UseG1GC=-XX:+PrintGC"))
|
||||
|
|
@ -140,7 +164,8 @@ object SbtScriptTest extends SimpleTestSuite with PowerAssertions {
|
|||
test("sbt with -debug in SBT_OPTS appears in sbt commands") {
|
||||
if (isWindows) cancel("Test not supported on windows")
|
||||
|
||||
val out: List[String] = sbtProcessWithOpts("compile", "-v")(javaOpts = "", sbtOpts = "-debug").!!.linesIterator.toList
|
||||
val out: List[String] =
|
||||
sbtProcessWithOpts("compile", "-v")(javaOpts = "", sbtOpts = "-debug").!!.linesIterator.toList
|
||||
// Debug argument must appear in the 'commands' section (after the sbt-launch.jar argument) to work
|
||||
val sbtLaunchMatcher = """^.+sbt-launch.jar["]{0,1}$""".r
|
||||
val locationOfSbtLaunchJarArg = out.zipWithIndex.collectFirst {
|
||||
|
|
@ -155,7 +180,9 @@ object SbtScriptTest extends SimpleTestSuite with PowerAssertions {
|
|||
}
|
||||
|
||||
makeTest("sbt --jvm-debug <port>")("--jvm-debug", "12345", "-v") { out: List[String] =>
|
||||
assert(out.contains[String]("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=12345"))
|
||||
assert(
|
||||
out.contains[String]("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=12345")
|
||||
)
|
||||
}
|
||||
|
||||
makeTest("sbt --no-share adds three system properties")("--no-share") { out: List[String] =>
|
||||
|
|
@ -171,7 +198,7 @@ object SbtScriptTest extends SimpleTestSuite with PowerAssertions {
|
|||
|
||||
test("sbt --script-version should print sbtVersion") {
|
||||
val out = sbtProcess("--script-version").!!.trim
|
||||
val expectedVersion = "^"+SbtRunnerTest.versionRegEx+"$"
|
||||
val expectedVersion = "^" + SbtRunnerTest.versionRegEx + "$"
|
||||
assert(out.matches(expectedVersion))
|
||||
()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ set default_java_opts=-Dfile.encoding=UTF-8
|
|||
set sbt_jar=
|
||||
set build_props_sbt_version=
|
||||
set run_native_client=
|
||||
set shutdownall=
|
||||
|
||||
set sbt_args_print_version=
|
||||
set sbt_args_print_sbt_version=
|
||||
|
|
@ -49,6 +50,7 @@ set sbt_args_sbt_dir=
|
|||
set sbt_args_sbt_version=
|
||||
set sbt_args_mem=
|
||||
set sbt_args_client=
|
||||
set sbt_args_no_server=
|
||||
|
||||
rem users can set SBT_OPTS via .sbtopts
|
||||
if exist .sbtopts for /F %%A in (.sbtopts) do (
|
||||
|
|
@ -204,6 +206,15 @@ if defined _no_colors_arg (
|
|||
goto args_loop
|
||||
)
|
||||
|
||||
if "%~0" == "-no-server" set _no_server_arg=true
|
||||
if "%~0" == "--no-server" set _no_server_arg=true
|
||||
|
||||
if defined _no_server_arg (
|
||||
set _no_server_arg=
|
||||
set sbt_args_no_server=1
|
||||
goto args_loop
|
||||
)
|
||||
|
||||
if "%~0" == "-no-global" set _no_global_arg=true
|
||||
if "%~0" == "--no-global" set _no_global_arg=true
|
||||
|
||||
|
|
@ -399,6 +410,11 @@ if defined _timings_arg (
|
|||
goto args_loop
|
||||
)
|
||||
|
||||
if "%~0" == "shutdownall" (
|
||||
set shutdownall=1
|
||||
goto args_loop
|
||||
)
|
||||
|
||||
if "%~0" == "--script-version" (
|
||||
set sbt_args_print_sbt_script_version=1
|
||||
goto args_loop
|
||||
|
|
@ -508,7 +524,7 @@ goto args_loop
|
|||
rem Confirm a user's intent if the current directory does not look like an sbt
|
||||
rem top-level directory and the "new" command was not given.
|
||||
|
||||
if not defined sbt_args_sbt_create if not defined sbt_args_print_version if not defined sbt_args_print_sbt_version if not defined sbt_args_print_sbt_script_version if not exist build.sbt (
|
||||
if not defined sbt_args_sbt_create if not defined sbt_args_print_version if not defined sbt_args_print_sbt_version if not defined sbt_args_print_sbt_script_version if not defined shutdownall if not exist build.sbt (
|
||||
if not exist project\ (
|
||||
if not defined sbt_new (
|
||||
echo [warn] Neither build.sbt nor a 'project' directory in the current directory: "%CD%"
|
||||
|
|
@ -535,6 +551,16 @@ call :process
|
|||
|
||||
rem avoid bootstrapping/java version check for script version
|
||||
|
||||
if !shutdownall! equ 1 (
|
||||
set count=0
|
||||
for /f "tokens=1" %%i in ('jps -lv ^| findstr "xsbt.boot.Boot"') do (
|
||||
taskkill /F /PID %%i
|
||||
set /a count=!count!+1
|
||||
)
|
||||
echo shutdown !count! sbt processes
|
||||
goto :eof
|
||||
)
|
||||
|
||||
if !sbt_args_print_sbt_script_version! equ 1 (
|
||||
echo !init_sbt_version!
|
||||
goto :eof
|
||||
|
|
@ -630,6 +656,10 @@ if defined sbt_args_traces (
|
|||
set _SBT_OPTS=-Dsbt.traces=true !_SBT_OPTS!
|
||||
)
|
||||
|
||||
if defined sbt_args_no_server (
|
||||
set _SBT_OPTS=-Dsbt.io.virtual=false -Dsbt.server.autostart=false !_SBT_OPTS!
|
||||
)
|
||||
|
||||
rem TODO: _SBT_OPTS needs to be processed as args and diffed against SBT_ARGS
|
||||
|
||||
if !sbt_args_print_sbt_version! equ 1 (
|
||||
|
|
|
|||
|
|
@ -36,3 +36,4 @@ else
|
|||
# Use Jansi to intercept ANSI sequences
|
||||
"$JAVA_CMD" -Dsbt.log.format=true $JAVA_OPTS $SBT_OPTS -cp "$WDIR/sbt-launch.jar" xsbt.boot.Boot "$@"
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import sbt.util.Logger
|
|||
import sbt.ConcurrentRestrictions.Tag
|
||||
import sbt.protocol.testing._
|
||||
import sbt.internal.util.Util.{ AnyOps, none }
|
||||
import sbt.internal.util.{ RunningProcesses, Terminal => UTerminal }
|
||||
import sbt.internal.util.{ Terminal => UTerminal }
|
||||
|
||||
private[sbt] object ForkTests {
|
||||
def apply(
|
||||
|
|
@ -158,13 +158,7 @@ private[sbt] object ForkTests {
|
|||
classOf[ForkMain].getCanonicalName,
|
||||
server.getLocalPort.toString
|
||||
)
|
||||
val p = Fork.java.fork(fork, options)
|
||||
RunningProcesses.add(p)
|
||||
val ec = try p.exitValue()
|
||||
finally {
|
||||
if (p.isAlive) p.destroy()
|
||||
RunningProcesses.remove(p)
|
||||
}
|
||||
val ec = Fork.java(fork, options)
|
||||
val result =
|
||||
if (ec != 0)
|
||||
TestOutput(
|
||||
|
|
@ -223,7 +217,7 @@ private final class React(
|
|||
listeners.foreach(_ testEvent event)
|
||||
val suiteResult = SuiteResult(tEvents)
|
||||
results += group -> suiteResult
|
||||
listeners.foreach(_ endGroup (group, suiteResult.result))
|
||||
listeners.foreach(_.endGroup(group, suiteResult.result))
|
||||
react()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ object Package {
|
|||
for ((key, value) <- mergeManifest.getEntries.asScala) {
|
||||
entryMap.get(key) match {
|
||||
case Some(attributes) => mergeAttributes(attributes, value); ()
|
||||
case None => entryMap put (key, value); ()
|
||||
case None => entryMap.put(key, value); ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ object RawCompileLike {
|
|||
log.debug("Uptodate: " + outputDirectory.getAbsolutePath)
|
||||
}
|
||||
}
|
||||
cachedComp(inputs)(exists(outputDirectory.allPaths.get.toSet))
|
||||
cachedComp(inputs)(exists(outputDirectory.allPaths.get().toSet))
|
||||
}
|
||||
|
||||
def prepare(description: String, doCompile: Gen): Gen =
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ final class Eval(
|
|||
if (phase == null || phase == phase.next || evalReporter.hasErrors)
|
||||
()
|
||||
else {
|
||||
enteringPhase(phase) { phase.run }
|
||||
enteringPhase(phase) { phase.run() }
|
||||
compile(phase.next)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class CacheIvyTest extends Properties("CacheIvy") {
|
|||
for {
|
||||
o <- Gen.identifier
|
||||
n <- Gen.identifier
|
||||
r <- for { n <- Gen.numChar; ns <- Gen.numStr } yield n + ns
|
||||
r <- for { n <- Gen.numChar; ns <- Gen.numStr } yield s"$n$ns"
|
||||
cs <- arbitrary[Option[String]]
|
||||
branch <- arbitrary[Option[String]]
|
||||
isChanging <- arbitrary[Boolean]
|
||||
|
|
|
|||
|
|
@ -284,10 +284,11 @@ public class BootServerSocket implements AutoCloseable {
|
|||
public BootServerSocket(final AppConfiguration configuration)
|
||||
throws ServerAlreadyBootingException, IOException {
|
||||
final Path base = configuration.baseDirectory().toPath().toRealPath();
|
||||
final Path target = base.resolve("project").resolve("target");
|
||||
if (!isWindows) {
|
||||
final String actualSocketLocation = socketLocation(base);
|
||||
final Path target = Paths.get(actualSocketLocation).getParent();
|
||||
if (!Files.isDirectory(target)) Files.createDirectories(target);
|
||||
socketFile = Paths.get(socketLocation(base));
|
||||
socketFile = Paths.get(actualSocketLocation);
|
||||
} else {
|
||||
socketFile = null;
|
||||
}
|
||||
|
|
@ -301,13 +302,20 @@ public class BootServerSocket implements AutoCloseable {
|
|||
}
|
||||
}
|
||||
|
||||
public static String socketLocation(final Path base) throws UnsupportedEncodingException {
|
||||
public static String socketLocation(final Path base)
|
||||
throws UnsupportedEncodingException, IOException {
|
||||
final Path target = base.resolve("project").resolve("target");
|
||||
long hash = LongHashFunction.farmNa().hashBytes(target.toString().getBytes("UTF-8"));
|
||||
if (isWindows) {
|
||||
long hash = LongHashFunction.farmNa().hashBytes(target.toString().getBytes("UTF-8"));
|
||||
return "sbt-load" + hash;
|
||||
} else {
|
||||
return base.relativize(target.resolve("sbt-load.sock")).toString();
|
||||
final String alternativeSocketLocation =
|
||||
System.getenv().getOrDefault("XDG_RUNTIME_DIR", "/tmp");
|
||||
final Path alternativeSocketLocationRoot =
|
||||
Paths.get(alternativeSocketLocation).resolve(".sbt");
|
||||
final Path locationForSocket = alternativeSocketLocationRoot.resolve("sbt-socket" + hash);
|
||||
final Path pathForSocket = locationForSocket.resolve("sbt-load.sock");
|
||||
return pathForSocket.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ object BasicCommands {
|
|||
private[this] def completionsParser: Parser[String] = {
|
||||
val notQuoted = (NotQuoted ~ any.*) map { case (nq, s) => nq + s }
|
||||
val quotedOrUnquotedSingleArgument = Space ~> (StringVerbatim | StringEscapable | notQuoted)
|
||||
token(quotedOrUnquotedSingleArgument ?? "" examples ("", " "))
|
||||
token((quotedOrUnquotedSingleArgument ?? "").examples("", " "))
|
||||
}
|
||||
|
||||
def runCompletions(state: State)(input: String): State = {
|
||||
|
|
@ -199,7 +199,7 @@ object BasicCommands {
|
|||
val it = s.iterator
|
||||
var fail = false
|
||||
while (it.hasNext && !fail) {
|
||||
it.next match {
|
||||
it.next() match {
|
||||
case "" => fail = it.hasNext; ()
|
||||
case next => result += next; ()
|
||||
}
|
||||
|
|
@ -406,7 +406,7 @@ object BasicCommands {
|
|||
case Some(line) =>
|
||||
val newState = s
|
||||
.copy(
|
||||
onFailure = Some(Exec(Shell, None)),
|
||||
onFailure = Some(Exec(OldShell, None)),
|
||||
remainingCommands = Exec(line, s.source) +: Exec(OldShell, None) +: s.remainingCommands
|
||||
)
|
||||
.setInteractive(true)
|
||||
|
|
|
|||
|
|
@ -88,10 +88,10 @@ object CommandUtil {
|
|||
}
|
||||
|
||||
def layoutDetails(details: Map[String, String]): String =
|
||||
details.map { case (k, v) => k + "\n\n " + v } mkString ("\n", "\n\n", "\n")
|
||||
details.map { case (k, v) => k + "\n\n " + v }.mkString("\n", "\n\n", "\n")
|
||||
|
||||
final val HelpPatternFlags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE
|
||||
|
||||
private[sbt] def isSbtBuild(baseDir: File) =
|
||||
(baseDir / "project").exists() || (baseDir * "*.sbt").get.nonEmpty
|
||||
(baseDir / "project").exists() || (baseDir * "*.sbt").get().nonEmpty
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ private[sbt] object LegacyWatched {
|
|||
(ClearOnFailure :: next :: FailureWall :: repeat :: s)
|
||||
.put(ContinuousEventMonitor, monitor: EventMonitor)
|
||||
case Some(eventMonitor) =>
|
||||
Watched.printIfDefined(watched watchingMessage eventMonitor.state)
|
||||
Watched.printIfDefined(watched watchingMessage eventMonitor.state())
|
||||
@tailrec def impl(): State = {
|
||||
val triggered = try eventMonitor.awaitEvent()
|
||||
catch {
|
||||
|
|
@ -56,7 +56,7 @@ private[sbt] object LegacyWatched {
|
|||
false
|
||||
}
|
||||
if (triggered) {
|
||||
Watched.printIfDefined(watched triggeredMessage eventMonitor.state)
|
||||
Watched.printIfDefined(watched triggeredMessage eventMonitor.state())
|
||||
ClearOnFailure :: next :: FailureWall :: repeat :: s
|
||||
} else if (shouldTerminate) {
|
||||
while (System.in.available() > 0) System.in.read()
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ trait ConsoleInterface {
|
|||
}
|
||||
|
||||
/**
|
||||
* A NetworkClient connects to a running an sbt instance or starts a
|
||||
* A NetworkClient connects to a running sbt instance or starts a
|
||||
* new instance if there isn't already one running. Once connected,
|
||||
* it can send commands for sbt to run, it can send completions to sbt
|
||||
* and print the completions to stdout so that a shell can consume
|
||||
|
|
@ -78,15 +78,15 @@ trait ConsoleInterface {
|
|||
* needs to start it. It also contains the sbt command
|
||||
* arguments to send to the server if any are present.
|
||||
* @param console a logging instance. This can use a ConsoleAppender or
|
||||
* just simply print to a PrintSream.
|
||||
* just simply print to a PrintStream.
|
||||
* @param inputStream the InputStream from which the client reads bytes. It
|
||||
* is not hardcoded to System.in so that a NetworkClient
|
||||
* can be remotely controlled by a java process, which
|
||||
* is useful in test.
|
||||
* is useful in testing.
|
||||
* @param errorStream the sink for messages that we always want to be printed.
|
||||
* It is usually System.err but could be overridden in tests
|
||||
* or set to a null OutputStream if the NetworkClient needs
|
||||
* to be silent
|
||||
* to be silent.
|
||||
* @param printStream the sink for standard out messages. It is typically
|
||||
* System.out but in the case of completions, the bytes written
|
||||
* to System.out are usually treated as completion results
|
||||
|
|
@ -139,7 +139,7 @@ class NetworkClient(
|
|||
private val rebooting = new AtomicBoolean(false)
|
||||
private lazy val noTab = arguments.completionArguments.contains("--no-tab")
|
||||
private lazy val noStdErr = arguments.completionArguments.contains("--no-stderr") &&
|
||||
System.getenv("SBTC_AUTO_COMPLETE") == null
|
||||
!sys.env.contains("SBTN_AUTO_COMPLETE") && !sys.env.contains("SBTC_AUTO_COMPLETE")
|
||||
|
||||
private def mkSocket(file: File): (Socket, Option[String]) = ClientSocket.socket(file, useJNI)
|
||||
|
||||
|
|
@ -380,13 +380,13 @@ class NetworkClient(
|
|||
}
|
||||
if (!startServer) {
|
||||
val deadline = 5.seconds.fromNow
|
||||
while (socket.isEmpty && !deadline.isOverdue) {
|
||||
while (socket.isEmpty && !deadline.isOverdue()) {
|
||||
socket = Try(ClientSocket.localSocket(bootSocketName, useJNI)).toOption
|
||||
if (socket.isEmpty) Thread.sleep(20)
|
||||
}
|
||||
}
|
||||
val hook = new Thread(() => Option(sbtProcess.get).foreach(_.destroyForcibly()))
|
||||
Runtime.getRuntime.addShutdownHook(hook)
|
||||
val shutdown = new Thread(() => Option(sbtProcess.get).foreach(_.destroyForcibly()))
|
||||
Runtime.getRuntime.addShutdownHook(shutdown)
|
||||
var gotInputBack = false
|
||||
val readThreadAlive = new AtomicBoolean(true)
|
||||
/*
|
||||
|
|
@ -406,10 +406,13 @@ class NetworkClient(
|
|||
socket.foreach { s =>
|
||||
try {
|
||||
s.getInputStream.read match {
|
||||
case -1 | 0 => readThreadAlive.set(false)
|
||||
case 2 => gotInputBack = true
|
||||
case 5 => term.enterRawMode(); startInputThread()
|
||||
case 3 if gotInputBack => readThreadAlive.set(false)
|
||||
case -1 | 0 => readThreadAlive.set(false)
|
||||
case 2 => // STX: start of text
|
||||
gotInputBack = true
|
||||
case 5 => // ENQ: enquiry
|
||||
term.enterRawMode(); startInputThread()
|
||||
case 3 if gotInputBack => // ETX: end of text
|
||||
readThreadAlive.set(false)
|
||||
case i if gotInputBack => stdinBytes.offer(i)
|
||||
case i => printStream.write(i)
|
||||
}
|
||||
|
|
@ -441,8 +444,13 @@ class NetworkClient(
|
|||
while (!gotInputBack && !stdinBytes.isEmpty && socket.isDefined) {
|
||||
val out = s.getOutputStream
|
||||
val b = stdinBytes.poll
|
||||
out.write(b)
|
||||
out.flush()
|
||||
if (b == -1) {
|
||||
// server waits for user input but stinBytes has ended
|
||||
shutdown.run()
|
||||
} else {
|
||||
out.write(b)
|
||||
out.flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
process.foreach { p =>
|
||||
|
|
@ -483,7 +491,7 @@ class NetworkClient(
|
|||
try blockUntilStart()
|
||||
catch { case t: Throwable => t.printStackTrace() } finally {
|
||||
sbtProcess.set(null)
|
||||
Util.ignoreResult(Runtime.getRuntime.removeShutdownHook(hook))
|
||||
Util.ignoreResult(Runtime.getRuntime.removeShutdownHook(shutdown))
|
||||
}
|
||||
if (!portfile.exists()) throw new ServerFailedException
|
||||
if (attached.get && !stdinBytes.isEmpty) Option(inputThread.get).foreach(_.drain())
|
||||
|
|
@ -828,12 +836,12 @@ class NetworkClient(
|
|||
case -1 => (query, query, None, None) // shouldn't happen
|
||||
case i =>
|
||||
val rawPrefix = query.substring(0, i)
|
||||
val prefix = rawPrefix.replaceAllLiterally("\"", "").replaceAllLiterally("\\;", ";")
|
||||
val rawSuffix = query.substring(i).replaceAllLiterally("\\;", ";")
|
||||
val prefix = rawPrefix.replace("\"", "").replace("\\;", ";")
|
||||
val rawSuffix = query.substring(i).replace("\\;", ";")
|
||||
val suffix = if (rawSuffix.length > 1) rawSuffix.substring(1) else ""
|
||||
(rawPrefix, prefix, Some(rawSuffix), Some(suffix))
|
||||
}
|
||||
} else (query, query.replaceAllLiterally("\\;", ";"), None, None)
|
||||
} else (query, query.replace("\\;", ";"), None, None)
|
||||
val tailSpace = query.endsWith(" ") || query.endsWith("\"")
|
||||
val sanitizedQuery = suffix.foldLeft(prefix) { _ + _ }
|
||||
def getCompletions(query: String, sendCommand: Boolean): Seq[String] = {
|
||||
|
|
@ -877,7 +885,7 @@ class NetworkClient(
|
|||
}
|
||||
getCompletions(sanitizedQuery, true) collect {
|
||||
case c if inQuote => c
|
||||
case c if tailSpace && c.contains(" ") => c.replaceAllLiterally(prefix, "")
|
||||
case c if tailSpace && c.contains(" ") => c.replace(prefix, "")
|
||||
case c if !tailSpace => c.split(" ").last
|
||||
}
|
||||
}
|
||||
|
|
@ -1098,10 +1106,10 @@ object NetworkClient {
|
|||
launchJar = a
|
||||
.split("--sbt-launch-jar=")
|
||||
.lastOption
|
||||
.map(_.replaceAllLiterally("%20", " "))
|
||||
.map(_.replace("%20", " "))
|
||||
case "--sbt-launch-jar" if i + 1 < sanitized.length =>
|
||||
i += 1
|
||||
launchJar = Option(sanitized(i).replaceAllLiterally("%20", " "))
|
||||
launchJar = Option(sanitized(i).replace("%20", " "))
|
||||
case "-bsp" | "--bsp" => bsp = true
|
||||
case a if !a.startsWith("-") => commandArgs += a
|
||||
case a @ SysProp(key, value) =>
|
||||
|
|
@ -1123,7 +1131,7 @@ object NetworkClient {
|
|||
sbtArguments.toSeq,
|
||||
commandArgs.toSeq,
|
||||
completionArguments.toSeq,
|
||||
sbtScript.getOrElse(defaultSbtScript).replaceAllLiterally("%20", " "),
|
||||
sbtScript.getOrElse(defaultSbtScript).replace("%20", " "),
|
||||
bsp,
|
||||
launchJar
|
||||
)
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ abstract class ServerConnection(connection: Socket) {
|
|||
if (a.nonEmpty) {
|
||||
out.write(a)
|
||||
}
|
||||
writeEndLine
|
||||
writeEndLine()
|
||||
} catch {
|
||||
case e: IOException =>
|
||||
shutdown()
|
||||
|
|
@ -100,7 +100,7 @@ abstract class ServerConnection(connection: Socket) {
|
|||
out.close()
|
||||
connection.close()
|
||||
} catch { case e: IOException => e.printStackTrace() }
|
||||
onShutdown
|
||||
onShutdown()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ private[sbt] object UITask {
|
|||
this.synchronized(this.wait())
|
||||
Right("") // should be unreachable
|
||||
// JLine returns null on ctrl+d when there is no other input. This interprets
|
||||
// ctrl+d with no imput as an exit
|
||||
// ctrl+d with no input as an exit
|
||||
case None => Left(TerminateAction)
|
||||
case Some(s: String) =>
|
||||
s.trim() match {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ object JoinThread {
|
|||
t.interrupt()
|
||||
t.join(10)
|
||||
} catch { case e: InterruptedException => }
|
||||
if (t.isAlive && !deadline.isOverdue) impl()
|
||||
if (t.isAlive && !deadline.isOverdue()) impl()
|
||||
}
|
||||
impl()
|
||||
if (t.isAlive) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
package sbt
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import org.scalatest.FlatSpec
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import sbt.internal.util.complete.Parser
|
||||
|
||||
object MultiParserSpec {
|
||||
|
|
@ -22,7 +22,7 @@ object MultiParserSpec {
|
|||
}
|
||||
}
|
||||
import sbt.MultiParserSpec._
|
||||
class MultiParserSpec extends FlatSpec {
|
||||
class MultiParserSpec extends AnyFlatSpec {
|
||||
"parsing" should "parse single commands" in {
|
||||
assert(";foo".parse == Seq("foo"))
|
||||
assert("; foo".parse == Seq("foo"))
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ package sbt.internal
|
|||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
|
||||
import org.scalatest.{ FlatSpec, Matchers }
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import sbt.internal.classpath.ClassLoaderCache
|
||||
import sbt.io.IO
|
||||
|
||||
|
|
@ -19,7 +20,7 @@ object ClassLoaderCacheTest {
|
|||
def get(classpath: Seq[File]): ClassLoader = c(classpath.toList)
|
||||
}
|
||||
}
|
||||
class ClassLoaderCacheTest extends FlatSpec with Matchers {
|
||||
class ClassLoaderCacheTest extends AnyFlatSpec with Matchers {
|
||||
import ClassLoaderCacheTest._
|
||||
private def withCache[R](f: ClassLoaderCache => R): R = {
|
||||
val cache = new ClassLoaderCache(ClassLoader.getSystemClassLoader)
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ object Def extends Init[Scope] with TaskMacroExtra with InitializeImplicits {
|
|||
)(l: Def.Initialize[Task[A => C]])(r: Def.Initialize[Task[B => C]]): Def.Initialize[Task[C]] = {
|
||||
val lhs = {
|
||||
val innerLhs: Def.Initialize[Task[Either[A, Either[B, C]]]] =
|
||||
x.map((fab: Either[A, B]) => fab.right.map(Left(_)))
|
||||
x.map((fab: Either[A, B]) => fab.map(Left(_)))
|
||||
val innerRhs: Def.Initialize[Task[A => Either[B, C]]] =
|
||||
l.map((fn: A => C) => fn.andThen(Right(_)))
|
||||
selectITask(innerLhs, innerRhs)
|
||||
|
|
|
|||
|
|
@ -34,4 +34,14 @@ object Remove {
|
|||
def removeValue(a: Seq[T], b: Option[T]): Seq[T] = b.fold(a)(a filterNot _.==)
|
||||
def removeValues(a: Seq[T], b: Option[T]): Seq[T] = b.fold(a)(a filterNot _.==)
|
||||
}
|
||||
implicit def removeSet[T, V <: T]: Sequence[Set[T], Set[V], V] =
|
||||
new Sequence[Set[T], Set[V], V] {
|
||||
def removeValue(a: Set[T], b: V): Set[T] = a - b
|
||||
def removeValues(a: Set[T], b: Set[V]): Set[T] = a diff (b.toSeq: Seq[T]).toSet
|
||||
}
|
||||
implicit def removeMap[A, B, X <: A]: Sequence[Map[A, B], Seq[X], X] =
|
||||
new Sequence[Map[A, B], Seq[X], X] {
|
||||
def removeValue(a: Map[A, B], b: X): Map[A, B] = a - b
|
||||
def removeValues(a: Map[A, B], b: Seq[X]): Map[A, B] = a -- b
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
|
||||
package sbt
|
||||
|
||||
import org.scalatest.FlatSpec
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import sbt.internal.util.{ AttributeKey, AttributeMap }
|
||||
import sbt.io.syntax.file
|
||||
import scala.annotation.nowarn
|
||||
|
||||
class ScopeDisplaySpec extends FlatSpec {
|
||||
class ScopeDisplaySpec extends AnyFlatSpec {
|
||||
val project = ProjectRef(file("foo/bar"), "bar")
|
||||
val mangledName = "bar_slash_blah_blah_blah"
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
|
||||
package sbt.std
|
||||
|
||||
import org.scalatest.{ TestData, fixture }
|
||||
import org.scalatest.{ TestData, fixture, funsuite }
|
||||
import sbt.std.TestUtil._
|
||||
|
||||
import scala.tools.reflect.{ FrontEnd, ToolBoxError }
|
||||
|
||||
class TaskConfigSpec extends fixture.FunSuite with fixture.TestDataFixture {
|
||||
class TaskConfigSpec extends funsuite.FixtureAnyFunSuite with fixture.TestDataFixture {
|
||||
private def expectError(
|
||||
errorSnippet: String,
|
||||
compileOptions: String = "",
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ object Assign {
|
|||
val is = Seq(
|
||||
mk := 3,
|
||||
name := "asdf",
|
||||
tk := (math.random * 1000).toInt,
|
||||
tk := (math.random() * 1000).toInt,
|
||||
isk := dummys.value.parsed // should not compile: cannot use a task to define the parser
|
||||
// ik := { if( tsk.parsed.value == "blue") tk.value else mk.value }
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
package sbt.std.neg
|
||||
|
||||
import scala.tools.reflect.ToolBoxError
|
||||
import org.scalatest.{ TestData, fixture }
|
||||
import org.scalatest.{ TestData, fixture, funsuite }
|
||||
import sbt.std.{ TaskLinterDSLFeedback, TestUtil }
|
||||
import sbt.std.TestUtil._
|
||||
|
||||
class TaskNegSpec extends fixture.FunSuite with fixture.TestDataFixture {
|
||||
class TaskNegSpec extends funsuite.FixtureAnyFunSuite with fixture.TestDataFixture {
|
||||
def expectError(
|
||||
errorSnippet: String,
|
||||
compileOptions: String = "",
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ abstract class BackgroundJobService extends Closeable {
|
|||
start(logger, file)._2.apply()
|
||||
}
|
||||
|
||||
/** Same as shutown. */
|
||||
/** Same as shutdown. */
|
||||
def close(): Unit
|
||||
|
||||
/** Shuts down all background jobs. */
|
||||
|
|
|
|||
|
|
@ -116,7 +116,8 @@ object BuildPaths {
|
|||
private[this] def defaultGlobalZinc(globalBase: File) = globalBase / "zinc"
|
||||
|
||||
def configurationSources(base: File): Seq[File] =
|
||||
(base * (GlobFilter("*.sbt") - ".sbt")).get
|
||||
(base * (GlobFilter("*.sbt") - ".sbt"))
|
||||
.get()
|
||||
.sortBy(_.getName.toLowerCase(Locale.ENGLISH))
|
||||
def pluginDirectory(definitionBase: File) = definitionBase / PluginsDirectoryName
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
package sbt
|
||||
|
||||
import java.io.File
|
||||
|
||||
import java.util.regex.Pattern
|
||||
import sbt.Def.{ ScopedKey, Setting }
|
||||
import sbt.Keys._
|
||||
import sbt.SlashSyntax0._
|
||||
|
|
@ -284,8 +284,8 @@ object Cross {
|
|||
}
|
||||
|
||||
def logSwitchInfo(
|
||||
included: Seq[(ProjectRef, Seq[ScalaVersion])],
|
||||
excluded: Seq[(ProjectRef, Seq[ScalaVersion])]
|
||||
included: Seq[(ResolvedReference, ScalaVersion, Seq[ScalaVersion])],
|
||||
excluded: Seq[(ResolvedReference, Seq[ScalaVersion])]
|
||||
) = {
|
||||
|
||||
instance.foreach {
|
||||
|
|
@ -304,56 +304,96 @@ object Cross {
|
|||
def detailedLog(msg: => String) =
|
||||
if (switch.verbose) state.log.info(msg) else state.log.debug(msg)
|
||||
|
||||
def logProject: (ProjectRef, Seq[ScalaVersion]) => Unit = (proj, scalaVersions) => {
|
||||
val current = if (proj == currentRef) "*" else " "
|
||||
detailedLog(s" $current ${proj.project} ${scalaVersions.mkString("(", ", ", ")")}")
|
||||
def logProject: (ResolvedReference, Seq[ScalaVersion]) => Unit = (ref, scalaVersions) => {
|
||||
val current = if (ref == currentRef) "*" else " "
|
||||
ref match {
|
||||
case proj: ProjectRef =>
|
||||
detailedLog(s" $current ${proj.project} ${scalaVersions.mkString("(", ", ", ")")}")
|
||||
case _ => // don't log BuildRefs
|
||||
}
|
||||
}
|
||||
detailedLog("Switching Scala version on:")
|
||||
included.foreach(logProject.tupled)
|
||||
included.foreach { case (project, _, versions) => logProject(project, versions) }
|
||||
detailedLog("Excluding projects:")
|
||||
excluded.foreach(logProject.tupled)
|
||||
}
|
||||
|
||||
val projects: Seq[(ResolvedReference, Seq[ScalaVersion])] = {
|
||||
val projects: Seq[(ResolvedReference, Option[ScalaVersion], Seq[ScalaVersion])] = {
|
||||
val projectScalaVersions =
|
||||
structure.allProjectRefs.map(proj => proj -> crossVersions(extracted, proj))
|
||||
if (switch.version.force) {
|
||||
logSwitchInfo(projectScalaVersions, Nil)
|
||||
projectScalaVersions ++ structure.units.keys
|
||||
projectScalaVersions.map {
|
||||
case (ref, options) => (ref, Some(version), options)
|
||||
} ++ structure.units.keys
|
||||
.map(BuildRef.apply)
|
||||
.map(proj => proj -> crossVersions(extracted, proj))
|
||||
.map(proj => (proj, Some(version), crossVersions(extracted, proj)))
|
||||
} else if (version.contains('*')) {
|
||||
projectScalaVersions.map {
|
||||
case (project, scalaVersions) =>
|
||||
globFilter(version, scalaVersions) match {
|
||||
case Nil => (project, None, scalaVersions)
|
||||
case Seq(version) => (project, Some(version), scalaVersions)
|
||||
case multiple =>
|
||||
sys.error(
|
||||
s"Multiple crossScalaVersions matched query '$version': ${multiple.mkString(", ")}"
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val binaryVersion = CrossVersion.binaryScalaVersion(version)
|
||||
|
||||
val (included, excluded) = projectScalaVersions.partition {
|
||||
case (_, scalaVersions) =>
|
||||
scalaVersions.exists(v => CrossVersion.binaryScalaVersion(v) == binaryVersion)
|
||||
projectScalaVersions.map {
|
||||
case (project, scalaVersions) =>
|
||||
if (scalaVersions.exists(v => CrossVersion.binaryScalaVersion(v) == binaryVersion))
|
||||
(project, Some(version), scalaVersions)
|
||||
else
|
||||
(project, None, scalaVersions)
|
||||
}
|
||||
if (included.isEmpty) {
|
||||
sys.error(
|
||||
s"""Switch failed: no subprojects list "$version" (or compatible version) in crossScalaVersions setting.
|
||||
|If you want to force it regardless, call ++ $version!""".stripMargin
|
||||
)
|
||||
}
|
||||
logSwitchInfo(included, excluded)
|
||||
included
|
||||
}
|
||||
}
|
||||
|
||||
(setScalaVersionForProjects(version, instance, projects, state, extracted), projects.map(_._1))
|
||||
val included = projects.collect {
|
||||
case (project, Some(version), scalaVersions) => (project, version, scalaVersions)
|
||||
}
|
||||
val excluded = projects.collect {
|
||||
case (project, None, scalaVersions) => (project, scalaVersions)
|
||||
}
|
||||
|
||||
if (included.isEmpty) {
|
||||
sys.error(
|
||||
s"""Switch failed: no subprojects list "$version" (or compatible version) in crossScalaVersions setting.
|
||||
|If you want to force it regardless, call ++ $version!""".stripMargin
|
||||
)
|
||||
}
|
||||
|
||||
logSwitchInfo(included, excluded)
|
||||
|
||||
(setScalaVersionsForProjects(instance, included, state, extracted), included.map(_._1))
|
||||
}
|
||||
|
||||
private def setScalaVersionForProjects(
|
||||
version: String,
|
||||
def globFilter(pattern: String, candidates: Seq[String]): Seq[String] = {
|
||||
def createGlobRegex(remainingPattern: String): String =
|
||||
remainingPattern.indexOf("*") match {
|
||||
case -1 => Pattern.quote(remainingPattern)
|
||||
case n =>
|
||||
val chunk = Pattern.quote(remainingPattern.substring(0, n)) + ".*"
|
||||
if (remainingPattern.length > n)
|
||||
chunk + createGlobRegex(remainingPattern.substring(n + 1))
|
||||
else chunk
|
||||
}
|
||||
val compiledPattern = Pattern.compile(createGlobRegex(pattern))
|
||||
candidates.filter(compiledPattern.matcher(_).matches())
|
||||
}
|
||||
|
||||
private def setScalaVersionsForProjects(
|
||||
instance: Option[(File, ScalaInstance)],
|
||||
projects: Seq[(ResolvedReference, Seq[String])],
|
||||
projects: Seq[(ResolvedReference, String, Seq[String])],
|
||||
state: State,
|
||||
extracted: Extracted
|
||||
): State = {
|
||||
import extracted._
|
||||
|
||||
val newSettings = projects.flatMap {
|
||||
case (project, scalaVersions) =>
|
||||
case (project, version, scalaVersions) =>
|
||||
val scope = Scope(Select(project), Zero, Zero, Zero)
|
||||
|
||||
instance match {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import sbt.internal.librarymanagement.mavenint.{
|
|||
PomExtraDependencyAttributes,
|
||||
SbtPomExtraProperties
|
||||
}
|
||||
import sbt.internal.librarymanagement.{ CustomHttp => _, _ }
|
||||
import sbt.internal.librarymanagement._
|
||||
import sbt.internal.nio.{ CheckBuildSources, Globs }
|
||||
import sbt.internal.server.{
|
||||
BspCompileProgress,
|
||||
|
|
@ -148,6 +148,7 @@ object Defaults extends BuildCommon {
|
|||
val m = (for (a <- cp; an <- a.metadata get Keys.analysis) yield (a.data, an)).toMap
|
||||
m.get _
|
||||
}
|
||||
|
||||
private[sbt] def globalDefaults(ss: Seq[Setting[_]]): Seq[Setting[_]] =
|
||||
Def.defaultSettings(inScope(GlobalScope)(ss))
|
||||
|
||||
|
|
@ -229,7 +230,7 @@ object Defaults extends BuildCommon {
|
|||
private[sbt] lazy val globalIvyCore: Seq[Setting[_]] =
|
||||
Seq(
|
||||
internalConfigurationMap :== Configurations.internalMap _,
|
||||
credentials :== Nil,
|
||||
credentials :== SysProp.sbtCredentialsEnv.toList,
|
||||
exportJars :== false,
|
||||
trackInternalDependencies :== TrackLevel.TrackAlways,
|
||||
exportToInternal :== TrackLevel.TrackAlways,
|
||||
|
|
@ -257,8 +258,6 @@ object Defaults extends BuildCommon {
|
|||
artifactClassifier :== None,
|
||||
checksums := Classpaths.bootChecksums(appConfiguration.value),
|
||||
conflictManager := ConflictManager.default,
|
||||
CustomHttp.okhttpClientBuilder :== CustomHttp.defaultHttpClientBuilder,
|
||||
CustomHttp.okhttpClient := CustomHttp.okhttpClientBuilder.value.build,
|
||||
pomExtra :== NodeSeq.Empty,
|
||||
pomPostProcess :== idFun,
|
||||
pomAllRepositories :== false,
|
||||
|
|
@ -1394,11 +1393,10 @@ object Defaults extends BuildCommon {
|
|||
val x = {
|
||||
import analysis.{ apis, relations => rel }
|
||||
rel.internalClassDeps(c).map(intlStamp(_, analysis, s + c)) ++
|
||||
rel.externalDeps(c).map(stamp) +
|
||||
(apis.internal.get(c) match {
|
||||
case Some(x) => x.compilationTimestamp
|
||||
case _ => Long.MinValue
|
||||
})
|
||||
rel.externalDeps(c).map(stamp) ++
|
||||
rel.productClassName.reverse(c).flatMap { pc =>
|
||||
apis.internal.get(pc).map(_.compilationTimestamp)
|
||||
} + Long.MinValue
|
||||
}.max
|
||||
if (x != Long.MinValue) {
|
||||
stamps(c) = x
|
||||
|
|
@ -2341,7 +2339,7 @@ object Defaults extends BuildCommon {
|
|||
s: TaskStreams,
|
||||
ci: Inputs,
|
||||
promise: PromiseWrap[Boolean],
|
||||
reporter: BuildServerReporter
|
||||
reporter: BuildServerReporter,
|
||||
): CompileResult = {
|
||||
lazy val x = s.text(ExportStream)
|
||||
def onArgs(cs: Compilers) = {
|
||||
|
|
@ -2634,7 +2632,7 @@ object Defaults extends BuildCommon {
|
|||
def dependencyResolutionTask: Def.Initialize[Task[DependencyResolution]] =
|
||||
Def.taskIf {
|
||||
if (useCoursier.value) CoursierDependencyResolution(csrConfiguration.value)
|
||||
else IvyDependencyResolution(ivyConfiguration.value, CustomHttp.okhttpClient.value)
|
||||
else IvyDependencyResolution(ivyConfiguration.value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3058,7 +3056,7 @@ object Classpaths {
|
|||
else None
|
||||
},
|
||||
dependencyResolution := dependencyResolutionTask.value,
|
||||
publisher := IvyPublisher(ivyConfiguration.value, CustomHttp.okhttpClient.value),
|
||||
publisher := IvyPublisher(ivyConfiguration.value),
|
||||
ivyConfiguration := mkIvyConfiguration.value,
|
||||
ivyConfigurations := {
|
||||
val confs = thisProject.value.configurations
|
||||
|
|
@ -3197,8 +3195,8 @@ object Classpaths {
|
|||
update / unresolvedWarningConfiguration := UnresolvedWarningConfiguration(
|
||||
dependencyPositions.value
|
||||
),
|
||||
updateFull := (updateTask tag (Tags.Update, Tags.Network)).value,
|
||||
update := (updateWithoutDetails("update") tag (Tags.Update, Tags.Network)).value,
|
||||
updateFull := (updateTask.tag(Tags.Update, Tags.Network)).value,
|
||||
update := (updateWithoutDetails("update").tag(Tags.Update, Tags.Network)).value,
|
||||
update := {
|
||||
val report = update.value
|
||||
val log = streams.value.log
|
||||
|
|
@ -3209,7 +3207,7 @@ object Classpaths {
|
|||
evicted / evictionWarningOptions := EvictionWarningOptions.full,
|
||||
evicted := {
|
||||
import ShowLines._
|
||||
val report = (updateTask tag (Tags.Update, Tags.Network)).value
|
||||
val report = (updateTask.tag(Tags.Update, Tags.Network)).value
|
||||
val log = streams.value.log
|
||||
val ew =
|
||||
EvictionWarning(ivyModule.value, (evicted / evictionWarningOptions).value, report)
|
||||
|
|
@ -3361,7 +3359,7 @@ object Classpaths {
|
|||
private[sbt] def ivySbt0: Initialize[Task[IvySbt]] =
|
||||
Def.task {
|
||||
Credentials.register(credentials.value, streams.value.log)
|
||||
new IvySbt(ivyConfiguration.value, CustomHttp.okhttpClient.value)
|
||||
new IvySbt(ivyConfiguration.value)
|
||||
}
|
||||
def moduleSettings0: Initialize[Task[ModuleSettings]] = Def.task {
|
||||
val deps = allDependencies.value.toVector
|
||||
|
|
@ -3701,7 +3699,7 @@ object Classpaths {
|
|||
try {
|
||||
val extracted = (Project extract st)
|
||||
val sk = (projRef / Zero / Zero / libraryDependencies).scopedKey
|
||||
val empty = extracted.structure.data set (sk.scope, sk.key, Nil)
|
||||
val empty = extracted.structure.data.set(sk.scope, sk.key, Nil)
|
||||
val settings = extracted.structure.settings filter { s: Setting[_] =>
|
||||
(s.key.key == libraryDependencies.key) &&
|
||||
(s.key.scope.project == Select(projRef))
|
||||
|
|
@ -4318,7 +4316,7 @@ trait BuildExtra extends BuildCommon with DefExtra {
|
|||
|
||||
/** Constructs a setting that declares a new artifact `a` that is generated by `taskDef`. */
|
||||
def addArtifact(a: Artifact, taskDef: TaskKey[File]): SettingsDefinition = {
|
||||
val pkgd = packagedArtifacts := packagedArtifacts.value updated (a, taskDef.value)
|
||||
val pkgd = packagedArtifacts := packagedArtifacts.value.updated(a, taskDef.value)
|
||||
Seq(artifacts += a, pkgd)
|
||||
}
|
||||
|
||||
|
|
@ -4330,7 +4328,7 @@ trait BuildExtra extends BuildCommon with DefExtra {
|
|||
val artLocal = SettingKey.local[Artifact]
|
||||
val taskLocal = TaskKey.local[File]
|
||||
val art = artifacts := artLocal.value +: artifacts.value
|
||||
val pkgd = packagedArtifacts := packagedArtifacts.value updated (artLocal.value, taskLocal.value)
|
||||
val pkgd = packagedArtifacts := packagedArtifacts.value.updated(artLocal.value, taskLocal.value)
|
||||
Seq(artLocal := artifact.value, taskLocal := taskDef.value, art, pkgd)
|
||||
}
|
||||
|
||||
|
|
@ -4380,7 +4378,7 @@ trait BuildExtra extends BuildCommon with DefExtra {
|
|||
}
|
||||
|
||||
@deprecated(
|
||||
"externalIvyFile is not supported by Couriser, and will be removed in the future",
|
||||
"externalIvyFile is not supported by Coursier, and will be removed in the future",
|
||||
since = "1.5.0"
|
||||
)
|
||||
def externalIvyFile(
|
||||
|
|
|
|||
|
|
@ -396,6 +396,7 @@ object Keys {
|
|||
val usePipelining = settingKey[Boolean]("Use subproject pipelining for compilation.").withRank(BSetting)
|
||||
val exportPipelining = settingKey[Boolean]("Product early output so downstream subprojects can do pipelining.").withRank(BSetting)
|
||||
|
||||
// BSP keys
|
||||
val bspConfig = taskKey[Unit]("Create or update the BSP connection files").withRank(DSetting)
|
||||
val bspEnabled = SettingKey[Boolean](BasicKeys.bspEnabled)
|
||||
val bspSbtEnabled = settingKey[Boolean]("Should BSP export meta-targets for the SBT build itself?")
|
||||
|
|
@ -418,8 +419,13 @@ object Keys {
|
|||
val bspBuildTargetCleanCache = inputKey[Unit]("Corresponds to buildTarget/cleanCache request").withRank(DTask)
|
||||
val bspBuildTargetScalacOptions = inputKey[Unit]("").withRank(DTask)
|
||||
val bspBuildTargetScalacOptionsItem = taskKey[ScalacOptionsItem]("").withRank(DTask)
|
||||
|
||||
val bspBuildTargetJVMRunEnvironment = inputKey[Unit]("Corresponds to the buildTarget/jvmRunEnvironment request").withRank(DTask)
|
||||
val bspBuildTargetJVMTestEnvironment = inputKey[Unit]("Corresponds to the buildTarget/jvmTestEnvironment request").withRank(DTask)
|
||||
val bspBuildTargetJvmEnvironmentItem = taskKey[JvmEnvironmentItem]("Computes JVM environment item").withRank(DTask)
|
||||
|
||||
val bspScalaTestClasses = inputKey[Unit]("Corresponds to buildTarget/scalaTestClasses request").withRank(DTask)
|
||||
val bspScalaTestClassesItem = taskKey[ScalaTestClassesItem]("").withRank(DTask)
|
||||
val bspScalaTestClassesItem = taskKey[Seq[ScalaTestClassesItem]]("").withRank(DTask)
|
||||
val bspScalaMainClasses = inputKey[Unit]("Corresponds to buildTarget/scalaMainClasses request").withRank(DTask)
|
||||
val bspScalaMainClassesItem = taskKey[ScalaMainClassesItem]("").withRank(DTask)
|
||||
val bspReporter = taskKey[BuildServerReporter]("").withRank(DTask)
|
||||
|
|
|
|||
|
|
@ -329,7 +329,6 @@ object BuiltinCommands {
|
|||
startServer,
|
||||
eval,
|
||||
last,
|
||||
oldLastGrep,
|
||||
lastGrep,
|
||||
export,
|
||||
boot,
|
||||
|
|
@ -626,12 +625,6 @@ object BuiltinCommands {
|
|||
s
|
||||
}
|
||||
|
||||
@deprecated("Use `lastGrep` instead.", "1.2.0")
|
||||
def oldLastGrep: Command =
|
||||
lastGrepCommand(OldLastGrepCommand, oldLastGrepBrief, oldLastGrepDetailed, { s =>
|
||||
lastGrepParser(s)
|
||||
})
|
||||
|
||||
def lastGrep: Command =
|
||||
lastGrepCommand(LastGrepCommand, lastGrepBrief, lastGrepDetailed, lastGrepParser)
|
||||
|
||||
|
|
@ -643,9 +636,6 @@ object BuiltinCommands {
|
|||
): Command =
|
||||
Command(name, briefHelp, detail)(parser) { (s: State, sks: (String, Option[AnyKeys])) =>
|
||||
{
|
||||
if (name == OldLastGrepCommand)
|
||||
s.log.warn(deprecationWarningText(OldLastGrepCommand, LastGrepCommand))
|
||||
|
||||
(s, sks) match {
|
||||
case (s, (pattern, Some(sks))) =>
|
||||
val (str, _, display) = extractLast(s)
|
||||
|
|
|
|||
|
|
@ -7,26 +7,22 @@
|
|||
|
||||
package sbt
|
||||
|
||||
import java.io.PrintWriter
|
||||
import java.util.concurrent.RejectedExecutionException
|
||||
import java.util.Properties
|
||||
|
||||
import sbt.BasicCommandStrings.{ StashOnFailure, networkExecPrefix }
|
||||
import sbt.internal.ShutdownHooks
|
||||
import sbt.internal.langserver.ErrorCodes
|
||||
import sbt.internal.protocol.JsonRpcResponseError
|
||||
import sbt.internal.nio.CheckBuildSources.CheckBuildSourcesKey
|
||||
import sbt.internal.protocol.JsonRpcResponseError
|
||||
import sbt.internal.util.{ ErrorHandling, GlobalLogBacking, Prompt, Terminal => ITerminal }
|
||||
import sbt.internal.{ ShutdownHooks, TaskProgress }
|
||||
import sbt.internal.{ FastTrackCommands, ShutdownHooks, SysProp, TaskProgress }
|
||||
import sbt.io.{ IO, Using }
|
||||
import sbt.protocol._
|
||||
import sbt.util.{ Logger, LoggerContext }
|
||||
|
||||
import java.io.PrintWriter
|
||||
import java.util.Properties
|
||||
import java.util.concurrent.RejectedExecutionException
|
||||
import scala.annotation.tailrec
|
||||
import scala.concurrent.duration._
|
||||
import scala.util.control.NonFatal
|
||||
import sbt.internal.FastTrackCommands
|
||||
import sbt.internal.SysProp
|
||||
|
||||
object MainLoop {
|
||||
|
||||
|
|
@ -148,7 +144,7 @@ object MainLoop {
|
|||
}
|
||||
|
||||
def next(state: State): State = {
|
||||
val context = LoggerContext(useLog4J = state.get(Keys.useLog4J.key).getOrElse(false))
|
||||
val context = LoggerContext()
|
||||
val superShellSleep =
|
||||
state.get(Keys.superShellSleep.key).getOrElse(SysProp.supershellSleep.millis)
|
||||
val superShellThreshold =
|
||||
|
|
|
|||
|
|
@ -41,8 +41,14 @@ object Opts {
|
|||
}
|
||||
object resolver {
|
||||
import sbt.io.syntax._
|
||||
@deprecated("Use sonatypeOssReleases instead", "1.7.0")
|
||||
val sonatypeReleases = Resolver.sonatypeRepo("releases")
|
||||
val sonatypeOssReleases = Resolver.sonatypeOssRepos("releases")
|
||||
|
||||
@deprecated("Use sonatypeOssSnapshots instead", "1.7.0")
|
||||
val sonatypeSnapshots = Resolver.sonatypeRepo("snapshots")
|
||||
val sonatypeOssSnapshots = Resolver.sonatypeOssRepos("snapshots")
|
||||
|
||||
val sonatypeStaging = MavenRepository(
|
||||
"sonatype-staging",
|
||||
"https://oss.sonatype.org/service/local/staging/deploy/maven2"
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ private[sbt] object PluginCross {
|
|||
VersionNumber(sv) match {
|
||||
case VersionNumber(Seq(0, 12, _*), _, _) => "2.9.2"
|
||||
case VersionNumber(Seq(0, 13, _*), _, _) => "2.10.7"
|
||||
case VersionNumber(Seq(1, 0, _*), _, _) => "2.12.15"
|
||||
case VersionNumber(Seq(1, 0, _*), _, _) => "2.12.16"
|
||||
case _ => sys.error(s"Unsupported sbt binary version: $sv")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import java.lang.reflect.Method
|
||||
|
||||
import sbt.Def._
|
||||
import sbt.Keys._
|
||||
|
|
@ -47,7 +46,7 @@ object ScriptedPlugin extends AutoPlugin {
|
|||
val scriptedParallelInstances = settingKey[Int](
|
||||
"Configures the number of scripted instances for parallel testing, only used in batch mode."
|
||||
)
|
||||
val scriptedRun = taskKey[Method]("")
|
||||
val scriptedRun = taskKey[ScriptedRun]("")
|
||||
val scriptedLaunchOpts =
|
||||
settingKey[Seq[String]]("options to pass to jvm launching scripted tasks")
|
||||
val scriptedDependencies = taskKey[Unit]("")
|
||||
|
|
@ -114,21 +113,8 @@ object ScriptedPlugin extends AutoPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
private[sbt] def scriptedRunTask: Initialize[Task[Method]] = Def.taskDyn {
|
||||
val fCls = classOf[File]
|
||||
val bCls = classOf[Boolean]
|
||||
val asCls = classOf[Array[String]]
|
||||
val lfCls = classOf[java.util.List[File]]
|
||||
val iCls = classOf[Int]
|
||||
|
||||
val clazz = scriptedTests.value.getClass
|
||||
val method =
|
||||
if (scriptedBatchExecution.value)
|
||||
clazz.getMethod("runInParallel", fCls, bCls, asCls, fCls, asCls, lfCls, iCls)
|
||||
else
|
||||
clazz.getMethod("run", fCls, bCls, asCls, fCls, asCls, lfCls)
|
||||
|
||||
Def.task(method)
|
||||
private[sbt] def scriptedRunTask: Initialize[Task[ScriptedRun]] = Def.task {
|
||||
ScriptedRun.of(scriptedTests.value, scriptedBatchExecution.value)
|
||||
}
|
||||
|
||||
private[sbt] final case class ScriptedTestPage(page: Int, total: Int)
|
||||
|
|
@ -191,21 +177,16 @@ object ScriptedPlugin extends AutoPlugin {
|
|||
private[sbt] def scriptedTask: Initialize[InputTask[Unit]] = Def.inputTask {
|
||||
val args = scriptedParser(sbtTestDirectory.value).parsed
|
||||
Def.unit(scriptedDependencies.value)
|
||||
try {
|
||||
val method = scriptedRun.value
|
||||
val scriptedInstance = scriptedTests.value
|
||||
val dir = sbtTestDirectory.value
|
||||
val log = Boolean box scriptedBufferLog.value
|
||||
val launcher = sbtLauncher.value
|
||||
val opts = scriptedLaunchOpts.value.toArray
|
||||
val empty = new java.util.ArrayList[File]()
|
||||
val instances = Int box scriptedParallelInstances.value
|
||||
|
||||
if (scriptedBatchExecution.value)
|
||||
method.invoke(scriptedInstance, dir, log, args.toArray, launcher, opts, empty, instances)
|
||||
else method.invoke(scriptedInstance, dir, log, args.toArray, launcher, opts, empty)
|
||||
()
|
||||
} catch { case e: java.lang.reflect.InvocationTargetException => throw e.getCause }
|
||||
scriptedRun.value.run(
|
||||
sbtTestDirectory.value,
|
||||
scriptedBufferLog.value,
|
||||
args,
|
||||
sbtLauncher.value,
|
||||
Fork.javaCommand((scripted / javaHome).value, "java").getAbsolutePath,
|
||||
scriptedLaunchOpts.value,
|
||||
new java.util.ArrayList[File](),
|
||||
scriptedParallelInstances.value
|
||||
)
|
||||
}
|
||||
|
||||
private[this] def getJars(config: Configuration): Initialize[Task[PathFinder]] = Def.task {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import java.lang.reflect.Method
|
||||
import scala.annotation.unused
|
||||
|
||||
sealed trait ScriptedRun {
|
||||
final def run(
|
||||
resourceBaseDirectory: File,
|
||||
bufferLog: Boolean,
|
||||
tests: Seq[String],
|
||||
launcherJar: File,
|
||||
javaCommand: String,
|
||||
launchOpts: Seq[String],
|
||||
prescripted: java.util.List[File],
|
||||
instances: Int,
|
||||
): Unit = {
|
||||
try {
|
||||
invoke(
|
||||
resourceBaseDirectory,
|
||||
bufferLog,
|
||||
tests.toArray,
|
||||
launcherJar,
|
||||
javaCommand,
|
||||
launchOpts.toArray,
|
||||
prescripted,
|
||||
instances,
|
||||
)
|
||||
()
|
||||
} catch { case e: java.lang.reflect.InvocationTargetException => throw e.getCause }
|
||||
}
|
||||
|
||||
protected def invoke(
|
||||
resourceBaseDirectory: File,
|
||||
bufferLog: java.lang.Boolean,
|
||||
tests: Array[String],
|
||||
launcherJar: File,
|
||||
javaCommand: String,
|
||||
launchOpts: Array[String],
|
||||
prescripted: java.util.List[File],
|
||||
instances: java.lang.Integer,
|
||||
): AnyRef
|
||||
|
||||
}
|
||||
|
||||
object ScriptedRun {
|
||||
|
||||
def of(scriptedTests: AnyRef, batchExecution: Boolean): ScriptedRun = {
|
||||
val fCls = classOf[File]
|
||||
val bCls = classOf[Boolean]
|
||||
val asCls = classOf[Array[String]]
|
||||
val sCls = classOf[String]
|
||||
val lfCls = classOf[java.util.List[File]]
|
||||
val iCls = classOf[Int]
|
||||
|
||||
val clazz = scriptedTests.getClass
|
||||
if (batchExecution)
|
||||
try new RunInParallelV2(
|
||||
scriptedTests,
|
||||
clazz.getMethod("runInParallel", fCls, bCls, asCls, fCls, sCls, asCls, lfCls, iCls)
|
||||
)
|
||||
catch {
|
||||
case _: NoSuchMethodException =>
|
||||
new RunInParallelV1(
|
||||
scriptedTests,
|
||||
clazz.getMethod("runInParallel", fCls, bCls, asCls, fCls, asCls, lfCls, iCls)
|
||||
)
|
||||
}
|
||||
else
|
||||
try new RunV2(
|
||||
scriptedTests,
|
||||
clazz.getMethod("run", fCls, bCls, asCls, fCls, sCls, asCls, lfCls)
|
||||
)
|
||||
catch {
|
||||
case _: NoSuchMethodException =>
|
||||
new RunV1(scriptedTests, clazz.getMethod("run", fCls, bCls, asCls, fCls, asCls, lfCls))
|
||||
}
|
||||
}
|
||||
|
||||
private class RunV1(scriptedTests: AnyRef, run: Method) extends ScriptedRun {
|
||||
override protected def invoke(
|
||||
resourceBaseDirectory: File,
|
||||
bufferLog: java.lang.Boolean,
|
||||
tests: Array[String],
|
||||
launcherJar: File,
|
||||
@unused javaCommand: String,
|
||||
launchOpts: Array[String],
|
||||
prescripted: java.util.List[File],
|
||||
@unused instances: java.lang.Integer,
|
||||
): AnyRef =
|
||||
run.invoke(
|
||||
scriptedTests,
|
||||
resourceBaseDirectory,
|
||||
bufferLog,
|
||||
tests,
|
||||
launcherJar,
|
||||
launchOpts,
|
||||
prescripted,
|
||||
)
|
||||
}
|
||||
|
||||
private class RunInParallelV1(scriptedTests: AnyRef, runInParallel: Method) extends ScriptedRun {
|
||||
override protected def invoke(
|
||||
resourceBaseDirectory: File,
|
||||
bufferLog: java.lang.Boolean,
|
||||
tests: Array[String],
|
||||
launcherJar: File,
|
||||
@unused javaCommand: String,
|
||||
launchOpts: Array[String],
|
||||
prescripted: java.util.List[File],
|
||||
instances: Integer,
|
||||
): AnyRef =
|
||||
runInParallel.invoke(
|
||||
scriptedTests,
|
||||
resourceBaseDirectory,
|
||||
bufferLog,
|
||||
tests,
|
||||
launcherJar,
|
||||
launchOpts,
|
||||
prescripted,
|
||||
instances,
|
||||
)
|
||||
}
|
||||
|
||||
private class RunV2(scriptedTests: AnyRef, run: Method) extends ScriptedRun {
|
||||
override protected def invoke(
|
||||
resourceBaseDirectory: File,
|
||||
bufferLog: java.lang.Boolean,
|
||||
tests: Array[String],
|
||||
launcherJar: File,
|
||||
javaCommand: String,
|
||||
launchOpts: Array[String],
|
||||
prescripted: java.util.List[File],
|
||||
@unused instances: java.lang.Integer,
|
||||
): AnyRef =
|
||||
run.invoke(
|
||||
scriptedTests,
|
||||
resourceBaseDirectory,
|
||||
bufferLog,
|
||||
tests,
|
||||
launcherJar,
|
||||
javaCommand,
|
||||
launchOpts,
|
||||
prescripted,
|
||||
)
|
||||
}
|
||||
|
||||
private class RunInParallelV2(scriptedTests: AnyRef, runInParallel: Method) extends ScriptedRun {
|
||||
override protected def invoke(
|
||||
resourceBaseDirectory: File,
|
||||
bufferLog: java.lang.Boolean,
|
||||
tests: Array[String],
|
||||
launcherJar: File,
|
||||
javaCommand: String,
|
||||
launchOpts: Array[String],
|
||||
prescripted: java.util.List[File],
|
||||
instances: Integer,
|
||||
): AnyRef =
|
||||
runInParallel.invoke(
|
||||
scriptedTests,
|
||||
resourceBaseDirectory,
|
||||
bufferLog,
|
||||
tests,
|
||||
launcherJar,
|
||||
javaCommand,
|
||||
launchOpts,
|
||||
prescripted,
|
||||
instances,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,12 +18,12 @@ trait UpperStateOps extends Any {
|
|||
|
||||
/**
|
||||
* ProjectRef to the current project of the state session that can be change using
|
||||
* `project` commmand.
|
||||
* `project` command.
|
||||
*/
|
||||
def currentRef: ProjectRef
|
||||
|
||||
/**
|
||||
* Current project of the state session that can be change using `project` commmand.
|
||||
* Current project of the state session that can be change using `project` command.
|
||||
*/
|
||||
def currentProject: ResolvedProject
|
||||
|
||||
|
|
|
|||
|
|
@ -57,16 +57,7 @@ object CoursierRepositoriesTasks {
|
|||
private final val keepPreloaded = false // coursierKeepPreloaded.value
|
||||
|
||||
def coursierResolversTask: Def.Initialize[sbt.Task[Seq[Resolver]]] = Def.task {
|
||||
val bootResOpt = bootResolvers.value
|
||||
val overrideFlag = overrideBuildResolvers.value
|
||||
val result0 = bootResOpt.filter(_ => overrideFlag) match {
|
||||
case Some(r) => r
|
||||
case None =>
|
||||
val extRes = externalResolvers.value
|
||||
val isSbtPlugin = sbtPlugin.value
|
||||
if (isSbtPlugin) sbtResolvers.value ++ extRes
|
||||
else extRes
|
||||
}
|
||||
val result0 = fullResolvers.value.filterNot(_ == projectResolver.value)
|
||||
val reorderResolvers = true // coursierReorderResolvers.value
|
||||
|
||||
val paths = ivyPaths.value
|
||||
|
|
@ -80,10 +71,10 @@ object CoursierRepositoriesTasks {
|
|||
result1 map {
|
||||
case r: FileRepository =>
|
||||
val ivyPatterns = r.patterns.ivyPatterns map {
|
||||
_.replaceAllLiterally("$" + "{ivy.home}", ivyHomeUri)
|
||||
_.replace("$" + "{ivy.home}", ivyHomeUri)
|
||||
}
|
||||
val artifactPatterns = r.patterns.artifactPatterns map {
|
||||
_.replaceAllLiterally("$" + "{ivy.home}", ivyHomeUri)
|
||||
_.replace("$" + "{ivy.home}", ivyHomeUri)
|
||||
}
|
||||
val p =
|
||||
r.patterns.withIvyPatterns(ivyPatterns).withArtifactPatterns(artifactPatterns)
|
||||
|
|
|
|||
|
|
@ -304,7 +304,12 @@ object Act {
|
|||
case Some(ProjectRef(uri, _)) => index.keys(Some(BuildRef(uri)), conf, task)
|
||||
case _ => Set()
|
||||
}
|
||||
val keys: Set[String] = index.keys(proj, conf, task) ++ buildKeys
|
||||
val globalKeys: Set[String] =
|
||||
proj match {
|
||||
case Some(_) => index.keys(None, conf, task)
|
||||
case _ => Set()
|
||||
}
|
||||
val keys: Set[String] = index.keys(proj, conf, task) ++ buildKeys ++ globalKeys
|
||||
keyParser(keys)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,15 @@ package sbt.internal
|
|||
private[sbt] object Banner {
|
||||
def apply(version: String): Option[String] =
|
||||
version match {
|
||||
case v if v.startsWith("1.6.0") =>
|
||||
Some(s"""
|
||||
|Here are some highlights of this release:
|
||||
| - Improved JDK 17 support
|
||||
| - Improved Build Server Protocol (BSP) support
|
||||
| - Tab completion of global keys
|
||||
|See https://eed3si9n.com/sbt-1.6.0 for full release notes.
|
||||
|Hide the banner for this release by running `skipBanner`.
|
||||
|""".stripMargin.linesIterator.mkString("\n"))
|
||||
case v if v.startsWith("1.4.0") =>
|
||||
Some(s"""
|
||||
|Here are some highlights of this release:
|
||||
|
|
|
|||
|
|
@ -263,7 +263,8 @@ final class BuildUnit(
|
|||
val plugins: LoadedPlugins
|
||||
) {
|
||||
override def toString =
|
||||
if (uri.getScheme == "file") localBase.toString else (uri + " (locally: " + localBase + ")")
|
||||
if (uri.getScheme == "file") localBase.toString
|
||||
else (uri.toString + " (locally: " + localBase + ")")
|
||||
}
|
||||
|
||||
final class LoadedBuild(val root: URI, val units: Map[URI, LoadedBuildUnit]) {
|
||||
|
|
|
|||
|
|
@ -70,23 +70,10 @@ $PrintCommand <task>
|
|||
def pluginsDetailed = pluginsBrief // TODO: expand
|
||||
|
||||
val LastCommand = "last"
|
||||
val OldLastGrepCommand = "last-grep"
|
||||
val LastGrepCommand = "lastGrep"
|
||||
val ExportCommand = "export"
|
||||
val ExportStream = "export"
|
||||
|
||||
val oldLastGrepBrief =
|
||||
(OldLastGrepCommand, "Shows lines from the last output for 'key' that match 'pattern'.")
|
||||
val oldLastGrepDetailed =
|
||||
s"""$OldLastGrepCommand <pattern>
|
||||
Displays lines from the logging of previous commands that match `pattern`.
|
||||
|
||||
$OldLastGrepCommand <pattern> [key]
|
||||
Displays lines from logging associated with `key` that match `pattern`. The key typically refers to a task (for example, test:compile). The logging that is displayed is restricted to the logging for that particular task.
|
||||
|
||||
<pattern> is a regular expression interpreted by java.util.Pattern. Matching text is highlighted (when highlighting is supported and enabled).
|
||||
See also '$LastCommand'."""
|
||||
|
||||
val lastGrepBrief =
|
||||
(LastGrepCommand, "Shows lines from the last output for 'key' that match 'pattern'.")
|
||||
val lastGrepDetailed =
|
||||
|
|
|
|||
|
|
@ -1128,7 +1128,28 @@ private[sbt] object Continuous extends DeprecatedContinuous {
|
|||
val callbacks: Callbacks,
|
||||
val dynamicInputs: mutable.Set[DynamicInput],
|
||||
val pending: Boolean,
|
||||
var failAction: Option[Watch.Action],
|
||||
) {
|
||||
def this(
|
||||
count: Int,
|
||||
commands: Seq[String],
|
||||
beforeCommandImpl: (State, mutable.Set[DynamicInput]) => State,
|
||||
afterCommand: State => State,
|
||||
afterWatch: State => State,
|
||||
callbacks: Callbacks,
|
||||
dynamicInputs: mutable.Set[DynamicInput],
|
||||
pending: Boolean,
|
||||
) = this(
|
||||
count,
|
||||
commands,
|
||||
beforeCommandImpl,
|
||||
afterCommand,
|
||||
afterWatch,
|
||||
callbacks,
|
||||
dynamicInputs,
|
||||
pending,
|
||||
None
|
||||
)
|
||||
def beforeCommand(state: State): State = beforeCommandImpl(state, dynamicInputs)
|
||||
def incremented: ContinuousState = withCount(count + 1)
|
||||
def withPending(p: Boolean) =
|
||||
|
|
@ -1208,7 +1229,7 @@ private[sbt] object ContinuousCommands {
|
|||
.channelForName(channelName)
|
||||
.getOrElse(throw new IllegalStateException(s"No channel with name $channelName"))
|
||||
val dynamicInputs = mutable.Set.empty[DynamicInput]
|
||||
val context = LoggerContext(useLog4J = state.get(Keys.useLog4J.key).getOrElse(false))
|
||||
val context = LoggerContext()
|
||||
def cb: Continuous.Callbacks =
|
||||
Continuous.getCallbacks(state, channel, commands, cache, dynamicInputs, context)
|
||||
|
||||
|
|
@ -1323,7 +1344,8 @@ private[sbt] object ContinuousCommands {
|
|||
case Watch.Prompt => stop.map(_ :: s"$PromptChannel ${channel.name}" :: Nil mkString ";")
|
||||
case Watch.Run(commands) =>
|
||||
stop.map(_ +: commands.map(_.commandLine).filter(_.nonEmpty) mkString "; ")
|
||||
case Watch.HandleError(_) =>
|
||||
case a @ Watch.HandleError(_) =>
|
||||
cs.failAction = Some(a)
|
||||
stop.map(_ :: s"$failWatch ${channel.name}" :: Nil mkString "; ")
|
||||
case _ => stop
|
||||
}
|
||||
|
|
@ -1353,27 +1375,31 @@ private[sbt] object ContinuousCommands {
|
|||
}
|
||||
cs.afterCommand(postState)
|
||||
}
|
||||
private[sbt] val stopWatchCommand = watchCommand(stopWatch) { (channel, state) =>
|
||||
state.get(watchStates).flatMap(_.get(channel)) match {
|
||||
case Some(cs) =>
|
||||
val afterWatchState = cs.afterWatch(state)
|
||||
cs.callbacks.onExit()
|
||||
StandardMain.exchange
|
||||
.channelForName(channel)
|
||||
.foreach { c =>
|
||||
c.terminal.setPrompt(Prompt.Pending)
|
||||
c.unprompt(ConsoleUnpromptEvent(Some(CommandSource(channel))))
|
||||
private[this] val exitWatchShared = (error: Boolean) =>
|
||||
(channel: String, state: State) =>
|
||||
state.get(watchStates).flatMap(_.get(channel)) match {
|
||||
case Some(cs) =>
|
||||
val afterWatchState = cs.afterWatch(state)
|
||||
cs.callbacks.onExit()
|
||||
StandardMain.exchange
|
||||
.channelForName(channel)
|
||||
.foreach { c =>
|
||||
c.terminal.setPrompt(Prompt.Pending)
|
||||
c.unprompt(ConsoleUnpromptEvent(Some(CommandSource(channel))))
|
||||
}
|
||||
val newState = afterWatchState.get(watchStates) match {
|
||||
case None => afterWatchState
|
||||
case Some(w) => afterWatchState.put(watchStates, w - channel)
|
||||
}
|
||||
afterWatchState.get(watchStates) match {
|
||||
case None => afterWatchState
|
||||
case Some(w) => afterWatchState.put(watchStates, w - channel)
|
||||
}
|
||||
case _ => state
|
||||
}
|
||||
}
|
||||
private[sbt] val failWatchCommand = watchCommand(failWatch) { (channel, state) =>
|
||||
state.fail
|
||||
}
|
||||
val commands = cs.commands.mkString("; ")
|
||||
val count = cs.count
|
||||
val action = cs.failAction.getOrElse(Watch.CancelWatch)
|
||||
val st = cs.callbacks.onTermination(action, commands, count, newState)
|
||||
if (error) st.fail else st
|
||||
case _ => if (error) state.fail else state
|
||||
}
|
||||
private[sbt] val stopWatchCommand = watchCommand(stopWatch)(exitWatchShared(false))
|
||||
private[sbt] val failWatchCommand = watchCommand(failWatch)(exitWatchShared(true))
|
||||
/*
|
||||
* Creates a FileTreeRepository where it is safe to call close without inadvertently cancelling
|
||||
* still active watches.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import java.io.File
|
|||
import scala.collection.immutable.ListMap
|
||||
import scala.annotation.tailrec
|
||||
import scala.util.{ Try, Success, Failure }
|
||||
import sbt.io.Path
|
||||
import sbt.io.{ IO, Path }
|
||||
import sbt.io.syntax._
|
||||
import sbt.Cross._
|
||||
import sbt.Def.{ ScopedKey, Setting }
|
||||
|
|
@ -389,7 +389,7 @@ private[sbt] object CrossJava {
|
|||
|
||||
object JavaDiscoverConfig {
|
||||
object JavaHomeDir {
|
||||
private val regex = """(\w+-)?(java-|(?:adoptopen)?jdk-?)(bin-)?(1\.)?([0-9]+).*""".r
|
||||
private val regex = """(\w+-)??(java-|(?:adoptopen)?jdk-?)?(bin-)?(1\.)?([0-9]+).*""".r
|
||||
def unapply(s: CharSequence): Option[String] = {
|
||||
s match {
|
||||
case regex(vendor, _, _, m, n) => Some(JavaVersion(nullBlank(m) + n).toString)
|
||||
|
|
@ -447,15 +447,21 @@ private[sbt] object CrossJava {
|
|||
}.flatten
|
||||
}
|
||||
|
||||
class WindowsDiscoverConfig(base: File) extends JavaDiscoverConf {
|
||||
class WindowsDiscoverConfig(base: File, vendors: Seq[String] = Seq.empty)
|
||||
extends JavaDiscoverConf {
|
||||
|
||||
def candidates() = wrapNull(base.list())
|
||||
|
||||
def javaHomes: Vector[(String, File)] =
|
||||
candidates()
|
||||
.collect {
|
||||
case dir @ JavaHomeDir(version) =>
|
||||
version -> (base / dir)
|
||||
case dir @ JavaHomeDir(version) => version -> base / dir
|
||||
}
|
||||
.flatMap {
|
||||
case x if vendors.isEmpty => Vector(x)
|
||||
case (version, home) =>
|
||||
val jv = JavaVersion(version)
|
||||
vendors.map(jv.withVendor(_).toString -> home)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -482,10 +488,24 @@ private[sbt] object CrossJava {
|
|||
new LinuxDiscoverConfig(file("/usr") / "java"),
|
||||
new LinuxDiscoverConfig(file("/usr") / "lib" / "jvm"),
|
||||
new MacOsDiscoverConfig,
|
||||
new WindowsDiscoverConfig(file("C://Program Files/Java")),
|
||||
new WindowsDiscoverConfig(file("C://Program Files (x86)/Java")),
|
||||
new JavaHomeDiscoverConfig,
|
||||
)
|
||||
) ++ {
|
||||
if (IO.isWindows) {
|
||||
def discover(dir: String, vendors: String*) = new WindowsDiscoverConfig(file(dir), vendors)
|
||||
Vector(
|
||||
discover("C://Program Files/Java", "openjdk"),
|
||||
discover("C://Program Files/Eclipse Foundation", "temurin", "adopt"),
|
||||
discover("C://Program Files/Semeru", "semeru", "adopt-openj9"),
|
||||
discover("C://Program Files/Microsoft", "microsoft"),
|
||||
discover("C://Program Files/Amazon Corretto", "amazon-corretto"),
|
||||
discover("C://Program Files/Zulu", "zulu"),
|
||||
discover("C://Program Files/BellSoft", "liberica"),
|
||||
discover("C://Program Files (x86)/Java", "openjdk"),
|
||||
discover("C://Program Files (x86)/Eclipse Foundation", "temurin", "adopt"),
|
||||
discover("C://Program Files (x86)/Semeru", "semeru", "adopt-openj9"),
|
||||
)
|
||||
} else Vector.empty
|
||||
}
|
||||
}
|
||||
|
||||
def nullBlank(s: String): String =
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt.internal
|
||||
|
||||
import sbt.internal.librarymanagement.{ CustomHttp => LMCustomHttp }
|
||||
import okhttp3._
|
||||
|
||||
import sbt.BuildSyntax._
|
||||
import sbt.KeyRanks._
|
||||
|
||||
object CustomHttp {
|
||||
val okhttpClientBuilder =
|
||||
settingKey[OkHttpClient.Builder]("Builder for the HTTP client.").withRank(CSetting)
|
||||
val okhttpClient =
|
||||
settingKey[OkHttpClient]("HTTP client used for library management.").withRank(CSetting)
|
||||
|
||||
def defaultHttpClientBuilder: OkHttpClient.Builder = {
|
||||
LMCustomHttp.defaultHttpClientBuilder
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +90,7 @@ private[sbt] abstract class AbstractBackgroundJobService extends BackgroundJobSe
|
|||
// hooks for sending start/stop events
|
||||
protected def onAddJob(@deprecated("unused", "") job: JobHandle): Unit = ()
|
||||
protected def onRemoveJob(@deprecated("unused", "") job: JobHandle): Unit = ()
|
||||
private val context = LoggerContext(useLog4J)
|
||||
private val context = LoggerContext()
|
||||
|
||||
// this mutable state could conceptually go on State except
|
||||
// that then every task that runs a background job would have
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ private[sbt] object InstallSbtn {
|
|||
Def.inputKey[Unit]("install sbtn and tab completions").withRank(KeyRanks.BTask)
|
||||
private[sbt] def installSbtnImpl: Def.Initialize[InputTask[Unit]] = Def.inputTask {
|
||||
val inputVersion = Def.spaceDelimited("version").parsed.headOption
|
||||
val version = inputVersion.getOrElse(sbtVersion.value.replaceAllLiterally("-SNAPSHOT", ""))
|
||||
val version = inputVersion.getOrElse(sbtVersion.value.replace("-SNAPSHOT", ""))
|
||||
val term = terminal.value
|
||||
term.setMode(canonical = false, echo = false)
|
||||
val baseDirectory = BuildPaths.getGlobalBase(state.value).toPath
|
||||
|
|
|
|||
|
|
@ -8,16 +8,15 @@
|
|||
package sbt
|
||||
package internal
|
||||
|
||||
import java.io.PrintWriter
|
||||
|
||||
import sbt.Def.ScopedKey
|
||||
import sbt.Keys._
|
||||
import sbt.Scope.Global
|
||||
import sbt.SlashSyntax0._
|
||||
import sbt.internal.util.MainAppender._
|
||||
import sbt.internal.util.{ Terminal => ITerminal, _ }
|
||||
import sbt.util.{ Level, LogExchange, Logger, LoggerContext }
|
||||
import org.apache.logging.log4j.core.{ Appender => XAppender }
|
||||
import sbt.util.{ Level, Logger, LoggerContext }
|
||||
|
||||
import java.io.PrintWriter
|
||||
import scala.annotation.nowarn
|
||||
|
||||
sealed abstract class LogManager {
|
||||
|
|
@ -88,12 +87,6 @@ object LogManager {
|
|||
def defaultManager(console: ConsoleOut): LogManager =
|
||||
withLoggers((_, _) => defaultScreen(console))
|
||||
|
||||
@deprecated(
|
||||
"use defaults that takes AppenderSupplier instead of ScopedKey[_] => Seq[Appender]",
|
||||
"1.4.0"
|
||||
)
|
||||
def defaults(extra: ScopedKey[_] => Seq[XAppender], console: ConsoleOut): LogManager =
|
||||
defaults((sk: ScopedKey[_]) => extra(sk).map(new ConsoleAppenderFromLog4J("extra", _)), console)
|
||||
// This is called by Defaults.
|
||||
def defaults(extra: AppenderSupplier, console: ConsoleOut): LogManager =
|
||||
withLoggers(
|
||||
|
|
@ -298,14 +291,6 @@ object LogManager {
|
|||
s1
|
||||
}
|
||||
|
||||
@deprecated("No longer used.", "1.4.0")
|
||||
private[sbt] def progressLogger(appender: ConsoleAppender): ManagedLogger = {
|
||||
val log = LogExchange.logger("progress", None, None)
|
||||
LoggerContext.globalContext.clearAppenders("progress")
|
||||
LoggerContext.globalContext.addAppender("progress", appender -> Level.Info)
|
||||
log
|
||||
}
|
||||
|
||||
// This is the default implementation for the relay appender
|
||||
val defaultRelay: Unit => ConsoleAppender = _ => defaultRelayImpl
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ object RemoteCache {
|
|||
ivySbt := {
|
||||
Credentials.register(credentials.value, streams.value.log)
|
||||
val config0 = ivyConfiguration.value
|
||||
new IvySbt(config0, sbt.internal.CustomHttp.okhttpClient.value)
|
||||
new IvySbt(config0)
|
||||
},
|
||||
)
|
||||
) ++ inTask(pullRemoteCache)(
|
||||
|
|
@ -303,7 +303,8 @@ object RemoteCache {
|
|||
}
|
||||
found = true
|
||||
case Left(e) =>
|
||||
log.info(s"remote cache not found for ${v}")
|
||||
val classifier = seqa.map(_.classifier).mkString(" ")
|
||||
log.info(s"remote cache artifact not found for $p $classifier")
|
||||
log.debug(e.getMessage)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import sbt.util.Show
|
|||
import java.io.File
|
||||
|
||||
import Def.{ ScopedKey, compiled, flattenLocals }
|
||||
import sbt.internal.util.Terminal
|
||||
|
||||
import Predef.{ any2stringadd => _, _ }
|
||||
import sbt.io.IO
|
||||
|
|
@ -123,10 +122,4 @@ object Graph {
|
|||
|
||||
toAsciiLines(top, 0, Set.empty).mkString("\n")
|
||||
}
|
||||
|
||||
def defaultColumnSize: Int = {
|
||||
val termWidth = Terminal.console.getWidth
|
||||
if (termWidth > 20) termWidth - 8
|
||||
else 80 // ignore termWidth
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,9 @@ import scala.util.control.NonFatal
|
|||
import scala.concurrent.duration._
|
||||
import sbt.internal.util.{ Terminal => ITerminal, Util }
|
||||
import sbt.internal.util.complete.SizeParser
|
||||
import sbt.nio.Keys._
|
||||
import sbt.io.syntax._
|
||||
import sbt.librarymanagement.ivy.{ Credentials, FileCredentials }
|
||||
import sbt.nio.Keys._
|
||||
|
||||
// See also BuildPaths.scala
|
||||
// See also LineReader.scala
|
||||
|
|
@ -216,4 +217,7 @@ object SysProp {
|
|||
.getOrElse(linuxCache)
|
||||
baseCache.getAbsoluteFile / "v1"
|
||||
}
|
||||
|
||||
lazy val sbtCredentialsEnv: Option[Credentials] =
|
||||
sys.env.get("SBT_CREDENTIALS").map(raw => new FileCredentials(new File(raw)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,8 +70,9 @@ private[sbt] class TaskProgress(
|
|||
pending.clear()
|
||||
scheduler.shutdownNow()
|
||||
executor.shutdownNow()
|
||||
if (!executor.awaitTermination(1, TimeUnit.SECONDS) ||
|
||||
!scheduler.awaitTermination(1, TimeUnit.SECONDS)) {
|
||||
if (!executor.awaitTermination(30, TimeUnit.SECONDS) ||
|
||||
!scheduler.awaitTermination(30, TimeUnit.SECONDS)) {
|
||||
scala.Console.err.println("timed out closing the executor of supershell")
|
||||
throw new TimeoutException
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ package rendering
|
|||
import sbt.internal.util.Terminal.red
|
||||
|
||||
object AsciiTree {
|
||||
def asciiTree(graph: ModuleGraph): String = {
|
||||
def asciiTree(graph: ModuleGraph, graphWidth: Int): String = {
|
||||
val deps = graph.dependencyMap
|
||||
|
||||
// there should only be one root node (the project itself)
|
||||
|
|
@ -25,7 +25,7 @@ object AsciiTree {
|
|||
root,
|
||||
node => deps.getOrElse(node.id, Seq.empty[Module]),
|
||||
displayModule,
|
||||
Graph.defaultColumnSize
|
||||
graphWidth
|
||||
)
|
||||
}
|
||||
.mkString("\n")
|
||||
|
|
@ -36,7 +36,7 @@ object AsciiTree {
|
|||
module.id.idString +
|
||||
module.extraInfo +
|
||||
module.error.map(" (error: " + _ + ")").getOrElse("") +
|
||||
module.evictedByVersion.map(_ formatted " (evicted by: %s)").getOrElse(""),
|
||||
module.evictedByVersion.map(v => s" (evicted by: $v)").getOrElse(""),
|
||||
module.hadError
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ object DagreHTML {
|
|||
val graphString =
|
||||
URLEncoder
|
||||
.encode(dotGraph, "utf8")
|
||||
.replaceAllLiterally("+", "%20")
|
||||
.replace("+", "%20")
|
||||
|
||||
IO.write(
|
||||
new File(targetDirectory, "dependencies.dot.js"),
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ object LicenseInfo {
|
|||
.map {
|
||||
case (license, modules) =>
|
||||
license.getOrElse("No license specified") + "\n" +
|
||||
modules.map(_.id.idString formatted "\t %s").mkString("\n")
|
||||
modules.map(m => s"\t ${m.id.idString}").mkString("\n")
|
||||
}
|
||||
.mkString("\n\n")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,21 +10,20 @@ package internal
|
|||
package graph
|
||||
package rendering
|
||||
|
||||
import java.io.{ OutputStream, InputStream, FileOutputStream, File }
|
||||
import java.net.URI
|
||||
|
||||
import graph.{ Module, ModuleGraph }
|
||||
import sbt.internal.graph.codec.JsonProtocol.ModuleModelFormat
|
||||
import sbt.io.IO
|
||||
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter }
|
||||
|
||||
import java.io.{ File, FileOutputStream, InputStream, OutputStream }
|
||||
import java.net.URI
|
||||
import scala.annotation.{ nowarn, tailrec }
|
||||
import scala.util.parsing.json.{ JSONArray, JSONObject }
|
||||
|
||||
@nowarn object TreeView {
|
||||
def createJson(graph: ModuleGraph): String = {
|
||||
val trees = graph.roots
|
||||
val moduleModels = graph.roots
|
||||
.map(module => processSubtree(graph, module))
|
||||
.toList
|
||||
JSONArray(trees).toString
|
||||
val js = moduleModels.map(Converter.toJsonUnsafe(_))
|
||||
js.map(CompactPrinter).mkString("[", ",", "]")
|
||||
}
|
||||
|
||||
def createLink(graphJson: String, targetDirectory: File): URI = {
|
||||
|
|
@ -36,19 +35,30 @@ import scala.util.parsing.json.{ JSONArray, JSONObject }
|
|||
new URI(graphHTML.toURI.toString)
|
||||
}
|
||||
|
||||
private def processSubtree(graph: ModuleGraph, module: Module): JSONObject = {
|
||||
val children = graph.dependencyMap
|
||||
.getOrElse(module.id, List())
|
||||
.map(module => processSubtree(graph, module))
|
||||
.toList
|
||||
moduleAsJson(module, children)
|
||||
private[rendering] def processSubtree(
|
||||
graph: ModuleGraph,
|
||||
module: Module,
|
||||
parents: Set[GraphModuleId] = Set()
|
||||
): ModuleModel = {
|
||||
val cycle = parents.contains(module.id)
|
||||
val dependencies = if (cycle) List() else graph.dependencyMap.getOrElse(module.id, List())
|
||||
val children =
|
||||
dependencies
|
||||
.map(dependency => processSubtree(graph, dependency, parents + module.id))
|
||||
.toVector
|
||||
moduleAsModuleAgain(module, cycle, children)
|
||||
}
|
||||
|
||||
private def moduleAsJson(module: Module, children: List[JSONObject]): JSONObject = {
|
||||
private def moduleAsModuleAgain(
|
||||
module: Module,
|
||||
isCycle: Boolean,
|
||||
children: Vector[ModuleModel]
|
||||
): ModuleModel = {
|
||||
val eviction = module.evictedByVersion.map(version => s" (evicted by $version)").getOrElse("")
|
||||
val cycle = if (isCycle) " (cycle)" else ""
|
||||
val error = module.error.map(err => s" (errors: $err)").getOrElse("")
|
||||
val text = module.id.idString + eviction + error
|
||||
JSONObject(Map("text" -> text, "children" -> JSONArray(children)))
|
||||
val text = module.id.idString + eviction + error + cycle
|
||||
ModuleModel(text, children)
|
||||
}
|
||||
|
||||
def saveResource(resourcePath: String, to: File): Unit = {
|
||||
|
|
|
|||
|
|
@ -32,13 +32,16 @@ import sjsonnew.shaded.scalajson.ast.unsafe.{ JNull, JValue }
|
|||
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter, Parser => JsonParser }
|
||||
import xsbti.CompileFailed
|
||||
|
||||
import java.nio.file.Path
|
||||
import java.io.File
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import scala.collection.mutable
|
||||
|
||||
// import scala.annotation.nowarn
|
||||
import scala.util.control.NonFatal
|
||||
import scala.util.{ Failure, Success, Try }
|
||||
import scala.annotation.nowarn
|
||||
import sbt.testing.Framework
|
||||
|
||||
object BuildServerProtocol {
|
||||
import sbt.internal.bsp.codec.JsonProtocol._
|
||||
|
|
@ -49,7 +52,9 @@ object BuildServerProtocol {
|
|||
RunProvider(BuildServerConnection.languages),
|
||||
dependencySourcesProvider = true,
|
||||
resourcesProvider = true,
|
||||
canReload = true
|
||||
canReload = true,
|
||||
jvmRunEnvironmentProvider = true,
|
||||
jvmTestEnvironmentProvider = true,
|
||||
)
|
||||
|
||||
private val bspReload = "bspReload"
|
||||
|
|
@ -103,11 +108,7 @@ object BuildServerProtocol {
|
|||
}
|
||||
}.value,
|
||||
// https://github.com/build-server-protocol/build-server-protocol/blob/master/docs/specification.md#build-target-sources-request
|
||||
bspBuildTargetSources := Def.inputTaskDyn {
|
||||
val s = state.value
|
||||
val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
||||
val workspace = bspFullWorkspace.value.filter(targets)
|
||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
||||
bspBuildTargetSources := bspInputTask { (state, _, workspace, filter) =>
|
||||
// run the worker task concurrently
|
||||
Def.task {
|
||||
val items = bspBuildTargetSourcesItem.result.all(filter).value
|
||||
|
|
@ -116,82 +117,63 @@ object BuildServerProtocol {
|
|||
val base = loadedBuildUnit.localBase
|
||||
val sbtFiles = configurationSources(base)
|
||||
val pluginData = loadedBuildUnit.unit.plugins.pluginData
|
||||
val all = Vector.newBuilder[SourceItem]
|
||||
def add(fs: Seq[File], sourceItemKind: Int, generated: Boolean): Unit = {
|
||||
fs.foreach(f => all += (SourceItem(f.toURI, sourceItemKind, generated = generated)))
|
||||
}
|
||||
all += (SourceItem(
|
||||
loadedBuildUnit.unit.plugins.base.toURI,
|
||||
SourceItemKind.Directory,
|
||||
generated = false
|
||||
))
|
||||
add(pluginData.unmanagedSourceDirectories, SourceItemKind.Directory, generated = false)
|
||||
add(pluginData.unmanagedSources, SourceItemKind.File, generated = false)
|
||||
add(pluginData.managedSourceDirectories, SourceItemKind.Directory, generated = true)
|
||||
add(pluginData.managedSources, SourceItemKind.File, generated = true)
|
||||
add(sbtFiles, SourceItemKind.File, generated = false)
|
||||
Value(SourcesItem(id, all.result()))
|
||||
val dirs = pluginData.unmanagedSourceDirectories
|
||||
val sourceFiles = getStandaloneSourceFiles(pluginData.unmanagedSources, dirs)
|
||||
val managedDirs = pluginData.managedSourceDirectories
|
||||
val managedSourceFiles =
|
||||
getStandaloneSourceFiles(pluginData.managedSources, managedDirs)
|
||||
val items =
|
||||
dirs.map(toSourceItem(SourceItemKind.Directory, generated = false)) ++
|
||||
sourceFiles.map(toSourceItem(SourceItemKind.File, generated = false)) ++
|
||||
managedDirs.map(toSourceItem(SourceItemKind.Directory, generated = true)) ++
|
||||
managedSourceFiles.map(toSourceItem(SourceItemKind.File, generated = true)) ++
|
||||
sbtFiles.map(toSourceItem(SourceItemKind.File, generated = false))
|
||||
Value(SourcesItem(id, items.toVector))
|
||||
}
|
||||
val successfulItems = anyOrThrow(items ++ buildItems)
|
||||
val result = SourcesResult(successfulItems.toVector)
|
||||
s.respondEvent(result)
|
||||
state.respondEvent(result)
|
||||
}
|
||||
}.evaluated,
|
||||
bspBuildTargetSources / aggregate := false,
|
||||
bspBuildTargetResources := Def.inputTaskDyn {
|
||||
val s = state.value
|
||||
val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
||||
val workspace = bspFullWorkspace.value.filter(targets)
|
||||
workspace.warnIfBuildsNonEmpty(Method.Resources, s.log)
|
||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
||||
bspBuildTargetResources := bspInputTask { (state, _, workspace, filter) =>
|
||||
workspace.warnIfBuildsNonEmpty(Method.Resources, state.log)
|
||||
// run the worker task concurrently
|
||||
Def.task {
|
||||
val items = bspBuildTargetResourcesItem.result.all(filter).value
|
||||
val successfulItems = anyOrThrow(items)
|
||||
val result = ResourcesResult(successfulItems.toVector)
|
||||
s.respondEvent(result)
|
||||
state.respondEvent(result)
|
||||
}
|
||||
}.evaluated,
|
||||
bspBuildTargetResources / aggregate := false,
|
||||
bspBuildTargetDependencySources := Def.inputTaskDyn {
|
||||
val s = state.value
|
||||
val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
||||
val workspace = bspFullWorkspace.value.filter(targets)
|
||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
||||
bspBuildTargetDependencySources := bspInputTask { (state, _, workspace, filter) =>
|
||||
// run the worker task concurrently
|
||||
Def.task {
|
||||
import sbt.internal.bsp.codec.JsonProtocol._
|
||||
val items = bspBuildTargetDependencySourcesItem.result.all(filter).value
|
||||
val successfulItems = anyOrThrow(items)
|
||||
val result = DependencySourcesResult(successfulItems.toVector)
|
||||
s.respondEvent(result)
|
||||
state.respondEvent(result)
|
||||
}
|
||||
}.evaluated,
|
||||
bspBuildTargetDependencySources / aggregate := false,
|
||||
bspBuildTargetCompile := Def.inputTaskDyn {
|
||||
val s: State = state.value
|
||||
val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
||||
val workspace = bspFullWorkspace.value.filter(targets)
|
||||
workspace.warnIfBuildsNonEmpty(Method.Compile, s.log)
|
||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
||||
bspBuildTargetCompile := bspInputTask { (state, _, workspace, filter) =>
|
||||
workspace.warnIfBuildsNonEmpty(Method.Compile, state.log)
|
||||
Def.task {
|
||||
val statusCodes = Keys.bspBuildTargetCompileItem.result.all(filter).value
|
||||
val aggregatedStatusCode = allOrThrow(statusCodes) match {
|
||||
case Seq() => StatusCode.Success
|
||||
case codes => codes.max
|
||||
}
|
||||
s.respondEvent(BspCompileResult(None, aggregatedStatusCode))
|
||||
state.respondEvent(BspCompileResult(None, aggregatedStatusCode))
|
||||
}
|
||||
}.evaluated,
|
||||
bspBuildTargetCompile / aggregate := false,
|
||||
bspBuildTargetTest := bspTestTask.evaluated,
|
||||
bspBuildTargetTest / aggregate := false,
|
||||
bspBuildTargetCleanCache := Def.inputTaskDyn {
|
||||
val s: State = state.value
|
||||
val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
||||
val workspace = bspFullWorkspace.value.filter(targets)
|
||||
workspace.warnIfBuildsNonEmpty(Method.CleanCache, s.log)
|
||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
||||
bspBuildTargetCleanCache := bspInputTask { (state, targets, workspace, filter) =>
|
||||
workspace.warnIfBuildsNonEmpty(Method.CleanCache, state.log)
|
||||
Def.task {
|
||||
val results = Keys.clean.result.all(filter).value
|
||||
val successes = anyOrThrow(results).size
|
||||
|
|
@ -201,18 +183,12 @@ object BuildServerProtocol {
|
|||
// checking that the executed results plus this entry is equal to the total number of targets.
|
||||
// When rebuilding a single module, the root build isn't sent, just the requested targets.
|
||||
val cleaned = successes + workspace.builds.size == targets.size
|
||||
s.respondEvent(CleanCacheResult(None, cleaned))
|
||||
state.respondEvent(CleanCacheResult(None, cleaned))
|
||||
}
|
||||
}.evaluated,
|
||||
bspBuildTargetCleanCache / aggregate := false,
|
||||
bspBuildTargetScalacOptions := Def.inputTaskDyn {
|
||||
val s = state.value
|
||||
|
||||
val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
||||
val workspace = bspFullWorkspace.value.filter(targets)
|
||||
bspBuildTargetScalacOptions := bspInputTask { (state, _, workspace, filter) =>
|
||||
val builds = workspace.builds
|
||||
|
||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
||||
Def.task {
|
||||
val items = bspBuildTargetScalacOptionsItem.result.all(filter).value
|
||||
val appProvider = appConfiguration.value.provider()
|
||||
|
|
@ -233,34 +209,26 @@ object BuildServerProtocol {
|
|||
}
|
||||
val successfulItems = anyOrThrow(items ++ buildItems)
|
||||
val result = ScalacOptionsResult(successfulItems.toVector)
|
||||
s.respondEvent(result)
|
||||
state.respondEvent(result)
|
||||
}
|
||||
}.evaluated,
|
||||
bspBuildTargetScalacOptions / aggregate := false,
|
||||
bspScalaTestClasses := Def.inputTaskDyn {
|
||||
val s = state.value
|
||||
val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
||||
val workspace = bspFullWorkspace.value.filter(targets)
|
||||
workspace.warnIfBuildsNonEmpty(Method.ScalaTestClasses, s.log)
|
||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
||||
bspScalaTestClasses := bspInputTask { (state, _, workspace, filter) =>
|
||||
workspace.warnIfBuildsNonEmpty(Method.ScalaTestClasses, state.log)
|
||||
Def.task {
|
||||
val items = bspScalaTestClassesItem.result.all(filter).value
|
||||
val successfulItems = anyOrThrow(items)
|
||||
val successfulItems = anyOrThrow(items).flatten.toVector
|
||||
val result = ScalaTestClassesResult(successfulItems.toVector, None)
|
||||
s.respondEvent(result)
|
||||
state.respondEvent(result)
|
||||
}
|
||||
}.evaluated,
|
||||
bspScalaMainClasses := Def.inputTaskDyn {
|
||||
val s = state.value
|
||||
val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
||||
val workspace = bspFullWorkspace.value.filter(targets)
|
||||
workspace.warnIfBuildsNonEmpty(Method.ScalaMainClasses, s.log)
|
||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
||||
bspScalaMainClasses := bspInputTask { (state, _, workspace, filter) =>
|
||||
workspace.warnIfBuildsNonEmpty(Method.ScalaMainClasses, state.log)
|
||||
Def.task {
|
||||
val items = bspScalaMainClassesItem.result.all(filter).value
|
||||
val successfulItems = anyOrThrow(items)
|
||||
val result = ScalaMainClassesResult(successfulItems.toVector, None)
|
||||
s.respondEvent(result)
|
||||
state.respondEvent(result)
|
||||
}
|
||||
}.evaluated,
|
||||
bspScalaMainClasses / aggregate := false
|
||||
|
|
@ -277,14 +245,14 @@ object BuildServerProtocol {
|
|||
bspBuildTargetSourcesItem := {
|
||||
val id = bspTargetIdentifier.value
|
||||
val dirs = unmanagedSourceDirectories.value
|
||||
val managed = managedSources.value
|
||||
val items = (dirs.toVector map { dir =>
|
||||
SourceItem(dir.toURI, SourceItemKind.Directory, generated = false)
|
||||
}) ++
|
||||
(managed.toVector map { x =>
|
||||
SourceItem(x.toURI, SourceItemKind.File, generated = true)
|
||||
})
|
||||
SourcesItem(id, items)
|
||||
val sourceFiles = getStandaloneSourceFiles(unmanagedSources.value, dirs)
|
||||
val managedDirs = managedSourceDirectories.value
|
||||
val managedSourceFiles = getStandaloneSourceFiles(managedSources.value, managedDirs)
|
||||
val items = dirs.map(toSourceItem(SourceItemKind.Directory, generated = false)) ++
|
||||
sourceFiles.map(toSourceItem(SourceItemKind.File, generated = false)) ++
|
||||
managedDirs.map(toSourceItem(SourceItemKind.Directory, generated = true)) ++
|
||||
managedSourceFiles.map(toSourceItem(SourceItemKind.File, generated = true))
|
||||
SourcesItem(id, items.toVector)
|
||||
},
|
||||
bspBuildTargetResourcesItem := {
|
||||
val id = bspTargetIdentifier.value
|
||||
|
|
@ -302,17 +270,42 @@ object BuildServerProtocol {
|
|||
bspBuildTargetCompileItem := bspCompileTask.value,
|
||||
bspBuildTargetRun := bspRunTask.evaluated,
|
||||
bspBuildTargetScalacOptionsItem := scalacOptionsTask.value,
|
||||
bspBuildTargetJVMRunEnvironment := bspInputTask { (state, _, _, filter) =>
|
||||
Def.task {
|
||||
val items = bspBuildTargetJvmEnvironmentItem.result.all(filter).value
|
||||
val successfulItems = anyOrThrow(items)
|
||||
val result = JvmRunEnvironmentResult(successfulItems.toVector, None)
|
||||
state.respondEvent(result)
|
||||
}
|
||||
}.evaluated,
|
||||
bspBuildTargetJVMTestEnvironment := bspInputTask { (state, _, _, filter) =>
|
||||
Def.task {
|
||||
val items = bspBuildTargetJvmEnvironmentItem.result.all(filter).value
|
||||
val successfulItems = anyOrThrow(items)
|
||||
val result = JvmTestEnvironmentResult(successfulItems.toVector, None)
|
||||
state.respondEvent(result)
|
||||
}
|
||||
}.evaluated,
|
||||
bspBuildTargetJvmEnvironmentItem := jvmEnvironmentItem().value,
|
||||
bspInternalDependencyConfigurations := internalDependencyConfigurationsSetting.value,
|
||||
bspScalaTestClassesItem := scalaTestClassesTask.value,
|
||||
bspScalaMainClassesItem := scalaMainClassesTask.value,
|
||||
Keys.compile / bspReporter := {
|
||||
val targetId = bspTargetIdentifier.value
|
||||
val bspCompileStateInstance = bspCompileState.value
|
||||
val converter = fileConverter.value
|
||||
val underlying = (Keys.compile / compilerReporter).value
|
||||
val logger = streams.value.log
|
||||
val meta = isMetaBuild.value
|
||||
if (bspEnabled.value) {
|
||||
new BuildServerReporterImpl(targetId, converter, meta, logger, underlying)
|
||||
new BuildServerReporterImpl(
|
||||
targetId,
|
||||
bspCompileStateInstance,
|
||||
converter,
|
||||
meta,
|
||||
logger,
|
||||
underlying
|
||||
)
|
||||
} else {
|
||||
new BuildServerForwarder(meta, logger, underlying)
|
||||
}
|
||||
|
|
@ -331,6 +324,8 @@ object BuildServerProtocol {
|
|||
final val Run = "buildTarget/run"
|
||||
final val CleanCache = "buildTarget/cleanCache"
|
||||
final val ScalacOptions = "buildTarget/scalacOptions"
|
||||
final val JvmRunEnvironment = "buildTarget/jvmRunEnvironment"
|
||||
final val JvmTestEnvironment = "buildTarget/jvmTestEnvironment"
|
||||
final val ScalaTestClasses = "buildTarget/scalaTestClasses"
|
||||
final val ScalaMainClasses = "buildTarget/scalaMainClasses"
|
||||
final val Exit = "build/exit"
|
||||
|
|
@ -429,6 +424,18 @@ object BuildServerProtocol {
|
|||
val command = Keys.bspBuildTargetScalacOptions.key
|
||||
val _ = callback.appendExec(s"$command $targets", Some(r.id))
|
||||
|
||||
case r if r.method == Method.JvmRunEnvironment =>
|
||||
val param = Converter.fromJson[JvmRunEnvironmentParams](json(r)).get
|
||||
val targets = param.targets.map(_.uri).mkString(" ")
|
||||
val command = Keys.bspBuildTargetJVMRunEnvironment.key
|
||||
val _ = callback.appendExec(s"$command $targets", Some(r.id))
|
||||
|
||||
case r if r.method == Method.JvmTestEnvironment =>
|
||||
val param = Converter.fromJson[JvmTestEnvironmentParams](json(r)).get
|
||||
val targets = param.targets.map(_.uri).mkString(" ")
|
||||
val command = Keys.bspBuildTargetJVMTestEnvironment.key
|
||||
val _ = callback.appendExec(s"$command $targets", Some(r.id))
|
||||
|
||||
case r if r.method == Method.ScalaTestClasses =>
|
||||
val param = Converter.fromJson[ScalaTestClassesParams](json(r)).get
|
||||
val targets = param.targets.map(_.uri).mkString(" ")
|
||||
|
|
@ -456,6 +463,18 @@ object BuildServerProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
private def getStandaloneSourceFiles(
|
||||
sourceFiles: Seq[File],
|
||||
sourceDirs: Seq[File]
|
||||
): Seq[File] = {
|
||||
sourceFiles.filterNot { f =>
|
||||
sourceDirs.exists(dir => f.toPath.startsWith(dir.toPath))
|
||||
}
|
||||
}
|
||||
|
||||
private def toSourceItem(itemKind: Int, generated: Boolean)(file: File): SourceItem =
|
||||
SourceItem(file.toURI, itemKind, generated)
|
||||
|
||||
private def checkMetalsCompatibility(
|
||||
semanticdbEnabled: Boolean,
|
||||
semanticdbVersion: String,
|
||||
|
|
@ -622,6 +641,38 @@ object BuildServerProtocol {
|
|||
)
|
||||
}
|
||||
|
||||
private def bspInputTask[T](
|
||||
taskImpl: (
|
||||
State,
|
||||
Seq[BuildTargetIdentifier],
|
||||
BspFullWorkspace,
|
||||
ScopeFilter
|
||||
) => Def.Initialize[Task[T]]
|
||||
): Def.Initialize[InputTask[T]] =
|
||||
Def.inputTaskDyn {
|
||||
val s = state.value
|
||||
val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
||||
val workspace: BspFullWorkspace = bspFullWorkspace.value.filter(targets)
|
||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
||||
taskImpl(s, targets, workspace, filter)
|
||||
}
|
||||
|
||||
private def jvmEnvironmentItem(): Initialize[Task[JvmEnvironmentItem]] = Def.task {
|
||||
val target = Keys.bspTargetIdentifier.value
|
||||
val classpath = Keys.fullClasspath.value.map(_.data.toURI).toVector
|
||||
val jvmOptions = Keys.javaOptions.value.toVector
|
||||
val baseDir = Keys.baseDirectory.value.toURI().toString()
|
||||
val env = envVars.value
|
||||
|
||||
JvmEnvironmentItem(
|
||||
target,
|
||||
classpath,
|
||||
jvmOptions,
|
||||
baseDir,
|
||||
env
|
||||
)
|
||||
}
|
||||
|
||||
private def scalacOptionsTask: Def.Initialize[Task[ScalacOptionsItem]] = Def.taskDyn {
|
||||
val target = Keys.bspTargetIdentifier.value
|
||||
val scalacOptions = Keys.scalacOptions.value
|
||||
|
|
@ -657,6 +708,10 @@ object BuildServerProtocol {
|
|||
DependencySourcesItem(targetId, sources.toVector.distinct)
|
||||
}
|
||||
|
||||
private def bspCompileState: Initialize[BuildServerProtocol.BspCompileState] = Def.setting {
|
||||
new BuildServerProtocol.BspCompileState()
|
||||
}
|
||||
|
||||
private def bspCompileTask: Def.Initialize[Task[Int]] = Def.task {
|
||||
Keys.compile.result.value match {
|
||||
case Value(_) => StatusCode.Success
|
||||
|
|
@ -831,15 +886,25 @@ object BuildServerProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
private def scalaTestClassesTask: Initialize[Task[ScalaTestClassesItem]] = Def.task {
|
||||
val testClasses = Keys.definedTests.?.value
|
||||
.getOrElse(Seq.empty)
|
||||
.map(_.name)
|
||||
.toVector
|
||||
ScalaTestClassesItem(
|
||||
bspTargetIdentifier.value,
|
||||
testClasses
|
||||
)
|
||||
private def scalaTestClassesTask: Initialize[Task[Seq[ScalaTestClassesItem]]] = Def.task {
|
||||
Keys.definedTests.?.value match {
|
||||
case None => Vector.empty
|
||||
case Some(definitions) =>
|
||||
val frameworks: Seq[Framework] = Keys.loadedTestFrameworks.?.value
|
||||
.map(_.values.toSeq)
|
||||
.getOrElse(Seq.empty)
|
||||
|
||||
val grouped = TestFramework.testMap(frameworks, definitions)
|
||||
|
||||
grouped.map {
|
||||
case (framework, definitions) =>
|
||||
ScalaTestClassesItem(
|
||||
bspTargetIdentifier.value,
|
||||
definitions.map(_.name).toVector,
|
||||
framework.name()
|
||||
)
|
||||
}.toSeq
|
||||
}
|
||||
}
|
||||
|
||||
private def scalaMainClassesTask: Initialize[Task[ScalaMainClassesItem]] = Def.task {
|
||||
|
|
@ -933,4 +998,20 @@ object BuildServerProtocol {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional information about compilation status for given build target.
|
||||
*
|
||||
* @param hasAnyProblems keeps track of problems in given file so BSP reporter
|
||||
* can omit unnecessary diagnostics updates.
|
||||
* @param compiledAtLeastOnce keeps track of those projects that were compiled at
|
||||
* least once so that we can decide to enable fresh reporting for projects that
|
||||
* are compiled for the first time.
|
||||
* see: https://github.com/scalacenter/bloop/issues/726
|
||||
*/
|
||||
private[server] final class BspCompileState {
|
||||
val hasAnyProblems: java.util.Set[Path] =
|
||||
java.util.concurrent.ConcurrentHashMap.newKeySet[Path]
|
||||
val compiledAtLeastOnce: AtomicBoolean = new AtomicBoolean(false)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue