mirror of https://github.com/sbt/sbt.git
commit
de4af16434
|
|
@ -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 := {
|
||||
|
|
|
|||
|
|
@ -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) ++
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.",
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 _ =>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue