Merge pull request #3818 from sbt/1.1.x

Merge 1.1.x to 1.x
This commit is contained in:
eugene yokota 2017-12-18 20:55:11 -05:00 committed by GitHub
commit de4af16434
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 146 additions and 64 deletions

View File

@ -9,7 +9,7 @@ def buildLevelSettings: Seq[Setting[_]] =
inThisBuild(
Seq(
organization := "org.scala-sbt",
version := "1.0.3-SNAPSHOT",
version := "1.1.0-SNAPSHOT",
description := "sbt is an interactive build tool",
bintrayOrganization := Some("sbt"),
bintrayRepository := {

View File

@ -485,7 +485,11 @@ private[sbt] object Eval {
def filesModifiedBytes(fs: Array[File]): Array[Byte] =
if (fs eq null) filesModifiedBytes(Array[File]()) else seqBytes(fs)(fileModifiedBytes)
def fileModifiedBytes(f: File): Array[Byte] =
(if (f.isDirectory) filesModifiedBytes(f listFiles classDirFilter) else bytes(f.lastModified)) ++
(if (f.isDirectory) filesModifiedBytes(f listFiles classDirFilter)
else
bytes(
try IO.getModifiedTime(f)
catch { case _: java.io.FileNotFoundException => 0L })) ++
bytes(f.getAbsolutePath)
def fileExistsBytes(f: File): Array[Byte] =
bytes(f.exists) ++

View File

@ -29,6 +29,8 @@ import java.nio.ByteBuffer;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Implements a {@link Socket} backed by a native Unix domain socket.
*
@ -41,6 +43,25 @@ public class NGUnixDomainSocket extends Socket {
private final InputStream is;
private final OutputStream os;
public NGUnixDomainSocket(String path) throws IOException {
try {
AtomicInteger fd = new AtomicInteger(
NGUnixDomainSocketLibrary.socket(
NGUnixDomainSocketLibrary.PF_LOCAL,
NGUnixDomainSocketLibrary.SOCK_STREAM,
0));
NGUnixDomainSocketLibrary.SockaddrUn address =
new NGUnixDomainSocketLibrary.SockaddrUn(path);
int socketFd = fd.get();
NGUnixDomainSocketLibrary.connect(socketFd, address, address.size());
this.fd = new ReferenceCountedFileDescriptor(socketFd);
this.is = new NGUnixDomainSocketInputStream();
this.os = new NGUnixDomainSocketOutputStream();
} catch (LastErrorException e) {
throw new IOException(e);
}
}
/**
* Creates a Unix domain socket backed by a native file descriptor.
*/

View File

@ -131,6 +131,8 @@ public class NGUnixDomainSocketLibrary {
public static native int listen(int fd, int backlog) throws LastErrorException;
public static native int accept(int fd, SockaddrUn address, IntByReference addressLen)
throws LastErrorException;
public static native int connect(int fd, SockaddrUn address, int addressLen)
throws LastErrorException;
public static native int read(int fd, ByteBuffer buffer, int count)
throws LastErrorException;
public static native int write(int fd, ByteBuffer buffer, int count)

View File

@ -11,6 +11,7 @@ import java.io.File
import sbt.internal.util.AttributeKey
import sbt.internal.inc.classpath.ClassLoaderCache
import sbt.librarymanagement.ModuleID
import sbt.util.Level
object BasicKeys {
val historyPath = AttributeKey[Option[File]](
@ -38,6 +39,14 @@ object BasicKeys {
"The wire protocol for the server command.",
10000)
// Unlike other BasicKeys, this is not used directly as a setting key,
// and severLog / logLevel is used instead.
private[sbt] val serverLogLevel =
AttributeKey[Level.Value]("serverLogLevel", "The log level for the server.", 10000)
private[sbt] val logLevel =
AttributeKey[Level.Value]("logLevel", "The amount of logging sent to the screen.", 10)
private[sbt] val interactive = AttributeKey[Boolean](
"interactive",
"True if commands are currently being entered from an interactive environment.",

View File

@ -9,7 +9,7 @@ package sbt
package internal
package server
import java.io.File
import java.io.{ File, IOException }
import java.net.{ SocketTimeoutException, InetAddress, ServerSocket, Socket }
import java.util.concurrent.atomic.AtomicBoolean
import java.nio.file.attribute.{ UserPrincipal, AclEntry, AclEntryPermission, AclEntryType }
@ -54,15 +54,17 @@ private[sbt] object Server {
val serverThread = new Thread("sbt-socket-server") {
override def run(): Unit = {
Try {
ErrorHandling.translate(s"server failed to start on ${connection.shortName}. ") {
connection.connectionType match {
case ConnectionType.Local if isWindows =>
new NGWin32NamedPipeServerSocket(pipeName)
case ConnectionType.Local =>
prepareSocketfile()
new NGUnixDomainServerSocket(socketfile.getAbsolutePath)
case ConnectionType.Tcp => new ServerSocket(port, 50, InetAddress.getByName(host))
}
connection.connectionType match {
case ConnectionType.Local if isWindows =>
// Named pipe already has an exclusive lock.
addServerError(new NGWin32NamedPipeServerSocket(pipeName))
case ConnectionType.Local =>
tryClient(new NGUnixDomainSocket(socketfile.getAbsolutePath))
prepareSocketfile()
addServerError(new NGUnixDomainServerSocket(socketfile.getAbsolutePath))
case ConnectionType.Tcp =>
tryClient(new Socket(InetAddress.getByName(host), port))
addServerError(new ServerSocket(port, 50, InetAddress.getByName(host)))
}
} match {
case Failure(e) => p.failure(e)
@ -87,6 +89,24 @@ private[sbt] object Server {
}
serverThread.start()
// Try the socket as a client to make sure that the server is not already up.
// f tries to connect to the server, and flip the result.
def tryClient(f: => Socket): Unit = {
if (portfile.exists) {
Try { f } match {
case Failure(e) => ()
case Success(socket) =>
socket.close()
throw new IOException("sbt server is already running.")
}
} else ()
}
def addServerError(f: => ServerSocket): ServerSocket =
ErrorHandling.translate(s"server failed to start on ${connection.shortName}. ") {
f
}
override def authenticate(challenge: String): Boolean = synchronized {
if (token == challenge) {
token = nextToken
@ -154,7 +174,7 @@ private[sbt] object Server {
auth match {
case _ if auth(ServerAuthentication.Token) =>
writeTokenfile()
PortFile(uri, Option(tokenfile.toString), Option(tokenfile.toURI.toString))
PortFile(uri, Option(tokenfile.toString), Option(IO.toURI(tokenfile).toString))
case _ =>
PortFile(uri, None, None)
}

View File

@ -2316,7 +2316,7 @@ object Classpaths {
case Some(period) =>
val fullUpdateOutput = cacheDirectory / "out"
val now = System.currentTimeMillis
val diff = now - fullUpdateOutput.lastModified()
val diff = now - IO.getModifiedTime(fullUpdateOutput)
val elapsedDuration = new FiniteDuration(diff, TimeUnit.MILLISECONDS)
fullUpdateOutput.exists() && elapsedDuration > period
}

View File

@ -94,7 +94,7 @@ object Keys {
val TraceValues = "-1 to disable, 0 for up to the first sbt frame, or a positive number to set the maximum number of frames shown."
// logging
val logLevel = settingKey[Level.Value]("The amount of logging sent to the screen.").withRank(ASetting)
val logLevel = SettingKey(BasicKeys.logLevel).withRank(ASetting)
val persistLogLevel = settingKey[Level.Value]("The amount of logging sent to a file for persistence.").withRank(CSetting)
val traceLevel = settingKey[Int]("The amount of a stack trace displayed. " + TraceValues).withRank(ASetting)
val persistTraceLevel = settingKey[Int]("The amount of stack trace persisted.").withRank(CSetting)
@ -105,6 +105,7 @@ object Keys {
val logManager = settingKey[LogManager]("The log manager, which creates Loggers for different contexts.").withRank(DSetting)
val logBuffered = settingKey[Boolean]("True if logging should be buffered until work completes.").withRank(CSetting)
val sLog = settingKey[Logger]("Logger usable by settings during project loading.").withRank(CSetting)
val serverLog = taskKey[Unit]("A dummy task to set server log level using Global / serverLog / logLevel.").withRank(CTask)
// Project keys
val autoGeneratedProject = settingKey[Boolean]("If it exists, represents that the project (and name) were automatically created, rather than user specified.").withRank(DSetting)

View File

@ -103,7 +103,7 @@ object StandardMain {
private[sbt] lazy val exchange = new CommandExchange()
import scalacache._
import scalacache.caffeine._
private[sbt] val cache: Cache[Any] = CaffeineCache[Any]
private[sbt] lazy val cache: Cache[Any] = CaffeineCache[Any]
def runManaged(s: State): xsbti.MainResult = {
val previous = TrapExit.installManager()
@ -135,9 +135,6 @@ object StandardMain {
Exec(x, None)
}
val initAttrs = BuiltinCommands.initialAttributes
import scalacache.modes.scalaFuture._
import scala.concurrent.ExecutionContext.Implicits.global
cache.removeAll()
val s = State(
configuration,
initialDefinitions,

View File

@ -11,6 +11,7 @@ import java.io.File
import java.net.URI
import java.util.Locale
import Project._
import BasicKeys.serverLogLevel
import Keys.{
stateBuildStructure,
commands,
@ -21,9 +22,11 @@ import Keys.{
shellPrompt,
templateResolverInfos,
serverHost,
serverLog,
serverPort,
serverAuthentication,
serverConnectionType,
logLevel,
watch
}
import Scope.{ Global, ThisScope }
@ -41,7 +44,7 @@ import sbt.internal.util.{ AttributeKey, AttributeMap, Dag, Relation, Settings,
import sbt.internal.util.Types.{ const, idFun }
import sbt.internal.util.complete.DefaultParsers
import sbt.librarymanagement.Configuration
import sbt.util.Show
import sbt.util.{ Show, Level }
import sjsonnew.JsonFormat
import language.experimental.macros
@ -463,6 +466,7 @@ object Project extends ProjectExtra {
val port: Option[Int] = get(serverPort)
val authentication: Option[Set[ServerAuthentication]] = get(serverAuthentication)
val connectionType: Option[ConnectionType] = get(serverConnectionType)
val srvLogLevel: Option[Level.Value] = (logLevel in (ref, serverLog)).get(structure.data)
val commandDefs = allCommands.distinct.flatten[Command].map(_ tag (projectCommand, true))
val newDefinedCommands = commandDefs ++ BasicCommands.removeTagged(s.definedCommands,
projectCommand)
@ -477,6 +481,7 @@ object Project extends ProjectExtra {
.put(historyPath.key, history)
.put(templateResolverInfos.key, trs)
.setCond(shellPrompt.key, prompt)
.setCond(serverLogLevel, srvLogLevel)
s.copy(
attributes = newAttrs,
definedCommands = newDefinedCommands

View File

@ -13,7 +13,14 @@ import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.atomic.AtomicInteger
import scala.collection.mutable.ListBuffer
import scala.annotation.tailrec
import BasicKeys.{ serverHost, serverPort, serverAuthentication, serverConnectionType }
import BasicKeys.{
serverHost,
serverPort,
serverAuthentication,
serverConnectionType,
serverLogLevel,
logLevel
}
import java.net.Socket
import sjsonnew.JsonFormat
import sjsonnew.shaded.scalajson.ast.unsafe._
@ -21,7 +28,7 @@ import scala.concurrent.Await
import scala.concurrent.duration.Duration
import scala.util.{ Success, Failure }
import sbt.io.syntax._
import sbt.io.Hash
import sbt.io.{ Hash, IO }
import sbt.internal.server._
import sbt.internal.langserver.{ LogMessageParams, MessageType }
import sbt.internal.util.{ StringEvent, ObjectEvent, MainAppender }
@ -106,7 +113,10 @@ private[sbt] final class CommandExchange {
case Some(x) => x
case None => ConnectionType.Tcp
}
val serverLogLevel: Level.Value = Level.Debug
lazy val level: Level.Value = (s get serverLogLevel)
.orElse(s get logLevel)
.getOrElse(Level.Warn)
def onIncomingSocket(socket: Socket, instance: ServerInstance): Unit = {
val name = newNetworkName
s.log.info(s"new client connected: $name")
@ -114,7 +124,7 @@ private[sbt] final class CommandExchange {
val log = LogExchange.logger(name, None, None)
LogExchange.unbindLoggerAppenders(name)
val appender = MainAppender.defaultScreen(s.globalLogging.console)
LogExchange.bindLoggerAppenders(name, List(appender -> serverLogLevel))
LogExchange.bindLoggerAppenders(name, List(appender -> level))
log
}
val channel =
@ -125,7 +135,7 @@ private[sbt] final class CommandExchange {
case Some(_) => // do nothing
case _ =>
val portfile = (new File(".")).getAbsoluteFile / "project" / "target" / "active.json"
val h = Hash.halfHashString(portfile.toURI.toString)
val h = Hash.halfHashString(IO.toURI(portfile).toString)
val tokenfile = BuildPaths.getGlobalBase(s) / "server" / h / "token.json"
val socketfile = BuildPaths.getGlobalBase(s) / "server" / h / "sock"
val pipeName = "sbt-server-" + h
@ -142,11 +152,13 @@ private[sbt] final class CommandExchange {
Await.ready(x.ready, Duration("10s"))
x.ready.value match {
case Some(Success(_)) =>
// rememeber to shutdown only when the server comes up
server = Some(x)
case Some(Failure(e)) =>
s.log.error(e.toString)
server = None
case None => // this won't happen because we awaited
}
server = Some(x)
}
s
}

View File

@ -13,6 +13,7 @@ import sbt.internal.librarymanagement._
import sbt.librarymanagement._
import sbt.librarymanagement.syntax._
import sbt.util.{ CacheStore, CacheStoreFactory, Logger, Tracked }
import sbt.io.IO
private[sbt] object LibraryManagement {
@ -126,7 +127,7 @@ private[sbt] object LibraryManagement {
}
private[this] def fileUptodate(file: File, stamps: Map[File, Long]): Boolean =
stamps.get(file).forall(_ == file.lastModified)
stamps.get(file).forall(_ == IO.getModifiedTime(file))
private[sbt] def transitiveScratch(
lm: DependencyResolution,

View File

@ -116,9 +116,7 @@ private[sbt] object SbtParser {
scalacGlobalInitReporter = Some(new ConsoleReporter(settings))
// Mix Positions, otherwise global ignores -Yrangepos
val global = new Global(settings, globalReporter) with Positions {
override protected def synchronizeNames = true // https://github.com/scala/bug/issues/10605
}
val global = new Global(settings, globalReporter) with Positions
val run = new global.Run
// Add required dummy unit for initialization...
val initFile = new BatchSourceFile("<wrapper-init>", "")
@ -151,7 +149,9 @@ private[sbt] object SbtParser {
val wrapperFile = new BatchSourceFile(reporterId, code)
val unit = new CompilationUnit(wrapperFile)
val parser = new syntaxAnalyzer.UnitParser(unit)
val parsedTrees = parser.templateStats()
val parsedTrees = SbtParser.synchronized { // see https://github.com/scala/bug/issues/10605
parser.templateStats()
}
parser.accept(scala.tools.nsc.ast.parser.Tokens.EOF)
globalReporter.throwParserErrorsIfAny(reporter, filePath)
parsedTrees -> reporterId

View File

@ -9,6 +9,7 @@ package sbt
package internal
package server
import sbt.io.IO
import sbt.internal.inc.MixedAnalyzingCompiler
import sbt.internal.langserver.ErrorCodes
import sbt.util.Logger
@ -297,7 +298,7 @@ private[sbt] object Definition {
textProcessor.markPosition(classFile, sym).collect {
case (file, line, from, to) =>
import sbt.internal.langserver.{ Location, Position, Range }
Location(file.toURI.toURL.toString,
Location(IO.toURI(file).toString,
Range(Position(line, from), Position(line, to)))
}
}

View File

@ -24,6 +24,7 @@ import sbt.internal.langserver.{
import sbt.internal.inc.JavaInterfaceUtil._
import scala.collection.mutable
import scala.collection.JavaConverters._
import sbt.io.IO
/**
* Defines a compiler reporter that uses event logging provided by a [[ManagedLogger]].
@ -82,7 +83,7 @@ class LanguageServerReporter(
import sbt.internal.langserver.codec.JsonProtocol._
val files = analysis.readSourceInfos.getAllSourceInfos.keySet.asScala
files foreach { f =>
val params = PublishDiagnosticsParams(f.toURI.toString, Vector())
val params = PublishDiagnosticsParams(IO.toURI(f).toString, Vector())
exchange.notifyEvent("textDocument/publishDiagnostics", params)
}
}
@ -94,7 +95,7 @@ class LanguageServerReporter(
problemsByFile.get(sourceFile) match {
case Some(xs: List[Problem]) =>
val ds = toDiagnostics(xs)
val params = PublishDiagnosticsParams(sourceFile.toURI.toString, ds)
val params = PublishDiagnosticsParams(IO.toURI(sourceFile).toString, ds)
exchange.notifyEvent("textDocument/publishDiagnostics", params)
case _ =>
}

View File

@ -1,3 +1,13 @@
### Changes since RC-1
- Fixes Java compilation causing `NullPointerException` by making PositionImpl thread-safe. [zinc#465](https://github.com/sbt/zinc/pull/465) by [@eed3si9n][@eed3si9n]
- Restores Scala 2.13.0-M1 support. #461 by @dwijnand
- Fixes `PollingWatchService` by preventing concurrent modification of `keysWithEvents` map. [io#90](https://github.com/sbt/io/pull/90) by [@mechkg][@mechkg], which fixes `~` related issues [#3687](https://github.com/sbt/sbt/issues/3687), [#3695](https://github.com/sbt/sbt/issues/3695), and [#3775](https://github.com/sbt/sbt/issues/3775).
- Fixed server spewing out debug level logs. [#3791](https://github.com/sbt/sbt/pull/3791) by [@eed3si9n][@eed3si9n]
- Fixes the encoding of Unix-like file path to use `file:///`. [#3805](https://github.com/sbt/sbt/pull/3805) by [@eed3si9n][@eed3si9n]
- Fixes Log4J2 initialization error during startup. [#3814](https://github.com/sbt/sbt/pull/3814) by [@dwijnand][@dwijnand]
- Provides workaround for `File#lastModified()` losing millisecond-precision by using native code when possible. [io#92](https://github.com/sbt/io/pull/92) by [@cunei][@cunei]
### Features, fixes, changes with compatibility implications
- sbt server feature is reworked in sbt 1.1.0. See below.
@ -112,7 +122,7 @@ Currently this extension is able to:
- Run `compile` at the root project when `*.scala` files are saved. [#3524][3524] by [@eed3si9n][@eed3si9n]
- Display compiler errors.
- Display log messages. [#3740][3740] by [@laughedelic][@laughedelic]
- Jump to class definitions. [#3660][3660]
- Jump to class definitions. [#3660][3660] by [@wpopielarski][@wpopielarski]
### Filtering scripted tests using `project/build.properties`
@ -122,6 +132,7 @@ This allows you to define scripted tests that track the minimum supported sbt ve
[@eed3si9n]: https://github.com/eed3si9n
[@dwijnand]: http://github.com/dwijnand
[@cunei]: https://github.com/cunei
[@jvican]: https://github.com/jvican
[@Duhemm]: https://github.com/Duhemm
[@jonas]: https://github.com/jonas
@ -136,6 +147,7 @@ This allows you to define scripted tests that track the minimum supported sbt ve
[@romanowski]: https://github.com/romanowski
[@raboof]: https://github.com/raboof
[@jilen]: https://github.com/jilen
[@mechkg]: https://github.com/mechkg
[vscode-sbt-scala]: https://marketplace.visualstudio.com/items?itemName=lightbend.vscode-sbt-scala
[1812]: https://github.com/sbt/sbt/issues/1812
[3524]: https://github.com/sbt/sbt/pull/3524

View File

@ -12,10 +12,10 @@ object Dependencies {
val baseScalaVersion = scala212
// sbt modules
private val ioVersion = "1.1.1"
private val utilVersion = "1.1.0"
private val lmVersion = "1.1.0"
private val zincVersion = "1.1.0-RC1"
private val ioVersion = "1.1.2"
private val utilVersion = "1.1.1"
private val lmVersion = "1.1.1"
private val zincVersion = "1.1.0-RC3"
private val sbtIO = "org.scala-sbt" %% "io" % ioVersion

View File

@ -68,6 +68,8 @@ object SiteMap {
// generates a string suitable for a sitemap file representing the last modified time of the given File
private[this] def lastModifiedString(f: File): String = {
val formatter = new java.text.SimpleDateFormat("yyyy-MM-dd")
// TODO: replace lastModified() with sbt.io.Milli.getModifiedTime(), once the build
// has been upgraded to a version of sbt that includes sbt.io.Milli.
formatter.format(new java.util.Date(f.lastModified))
}
// writes the provided XML node to `output` and then gzips it to `gzipped` if `gzip` is true

View File

@ -105,6 +105,8 @@ object Util {
val timestamp = formatter.format(new Date)
val content = versionLine(version) + "\ntimestamp=" + timestamp
val f = dir / "xsbt.version.properties"
// TODO: replace lastModified() with sbt.io.Milli.getModifiedTime(), once the build
// has been upgraded to a version of sbt that includes sbt.io.Milli.
if (!f.exists || f.lastModified < lastCompilationTime(analysis) || !containsVersion(f, version)) {
s.log.info("Writing version information to " + f + " :\n" + content)
IO.write(f, content)

View File

@ -1,15 +1,8 @@
scalaVersion := "2.12.3"
scalacOptions ++= Seq("-feature", "-language:postfixOps")
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.17")
// addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.0")
// addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.9.2")
// addSbtPlugin("com.typesafe.sbt" % "sbt-javaversioncheck" % "0.1.0")
// addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.2.0")
addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.1")
addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.1")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0-M1")
addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.4")
addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.2")
addSbtPlugin("com.lucidchart" % "sbt-scalafmt" % "1.14")
addSbtPlugin("de.heikoseeberger" % "sbt-header" % "3.0.2")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0")

View File

@ -9,7 +9,7 @@ final class ClientCapabilities private () extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: ClientCapabilities => true
case _: ClientCapabilities => true
case _ => false
}
override def hashCode: Int = {

View File

@ -11,7 +11,7 @@ abstract class CommandMessage() extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: CommandMessage => true
case _: CommandMessage => true
case _ => false
}
override def hashCode: Int = {

View File

@ -11,7 +11,7 @@ abstract class EventMessage() extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: EventMessage => true
case _: EventMessage => true
case _ => false
}
override def hashCode: Int = {

View File

@ -10,7 +10,7 @@ abstract class SettingQueryResponse() extends sbt.protocol.EventMessage() with S
override def equals(o: Any): Boolean = o match {
case x: SettingQueryResponse => true
case _: SettingQueryResponse => true
case _ => false
}
override def hashCode: Int = {

View File

@ -1,4 +1,4 @@
val baseSbt = "1.0"
val baseSbt = "1."
val buildCrossList = List("2.10.6", "2.11.11", "2.12.2")
scalaVersion in ThisBuild := "2.12.2"
@ -10,20 +10,20 @@ lazy val root = (project in file("."))
.settings(
sbtPlugin := true,
TaskKey[Unit]("check") := mkCheck("2.12", "1.0").value,
TaskKey[Unit]("check2") := mkCheck("2.10", "0.13").value
TaskKey[Unit]("check") := mkCheck("2.12", "1.0", "1.").value,
TaskKey[Unit]("check2") := mkCheck("2.10", "0.13", "0.13").value
)
lazy val app = (project in file("app"))
def mkCheck(scalaBinV: String, sbtBinVer: String) = Def task {
def mkCheck(scalaBinV: String, sbtBinVer: String, sbtVerPrefix: String) = Def task {
val crossV = (sbtVersion in pluginCrossBuild).value
val crossBinV = (sbtBinaryVersion in pluginCrossBuild).value
val sv = projectID.value.extraAttributes("e:scalaVersion")
assert(sbtVersion.value startsWith baseSbt, s"Wrong sbt version: ${sbtVersion.value}")
assert(sv == scalaBinV, s"Wrong e:scalaVersion: $sv")
assert(scalaBinaryVersion.value == scalaBinV, s"Wrong Scala binary version: ${scalaBinaryVersion.value}")
assert(crossV startsWith sbtBinVer, s"Wrong `sbtVersion in pluginCrossBuild`: $crossV")
assert(crossV startsWith sbtVerPrefix, s"Wrong `sbtVersion in pluginCrossBuild`: $crossV")
val ur = update.value
val cr = ur.configuration(Compile).get
@ -31,7 +31,7 @@ def mkCheck(scalaBinV: String, sbtBinVer: String) = Def task {
val plugSv = mr.module.extraAttributes("scalaVersion")
val plugSbtV = mr.module.extraAttributes("sbtVersion")
assert(plugSv == scalaBinV, s"Wrong plugin scalaVersion: $plugSv")
assert(plugSbtV == sbtBinVer, s"Wrong plugin scalaVersion: $sbtBinVer")
assert(plugSbtV == sbtBinVer, s"Wrong plugin sbtVersion: $plugSbtV")
// crossScalaVersions in app should not be affected, per se or after ^^
val appCrossScalaVersions = (crossScalaVersions in app).value.toList

View File

@ -13,7 +13,6 @@ $ copy-file changes/ThreadRunError.scala src/main/scala/Run.scala
$ copy-file changes/RunExplicitSuccess.scala src/main/scala/Run.scala
> run
# https://github.com/sbt/sbt/issues/3543
# # explicitly calling System.exit(1) should fail the 'run' task
# $ copy-file changes/RunExplicitFailure.scala src/main/scala/Run.scala
# -> run
# explicitly calling System.exit(1) should fail the 'run' task
$ copy-file changes/RunExplicitFailure.scala src/main/scala/Run.scala
-> run

View File

@ -10,7 +10,7 @@ final class TestInitEvent private () extends sbt.protocol.testing.TestMessage()
override def equals(o: Any): Boolean = o match {
case x: TestInitEvent => true
case _: TestInitEvent => true
case _ => false
}
override def hashCode: Int = {

View File

@ -11,7 +11,7 @@ abstract class TestMessage() extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: TestMessage => true
case _: TestMessage => true
case _ => false
}
override def hashCode: Int = {