Skip to content

Commit 1d027ec

Browse files
authored
Merge pull request sbt#7105 from eed3si9n/wip/merge-1.9.x
Merge 1.9.x into develop branch
2 parents e8c58df + bb40e1b commit 1d027ec

File tree

52 files changed

+222
-66
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+222
-66
lines changed

.github/ISSUE_TEMPLATE/--feature-request.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ assignees: ''
77

88
---
99

10-
Please use https://github.com/sbt/sbt/discussions including a specific user story instead of posting them to the issue tracker.
10+
If you have new ideas about sbt or an open-ended discussion, please use https://github.com/sbt/sbt/discussions instead of posting them to the issue tracker, which we use to track bugs and (internal) todo list.
11+
12+
Please note that sbt is mostly maintained by community effort, so one of the questions that we'd ask might be "would like to contribute it if we help you where the relevant code is".

.github/workflows/ci.yml

+7-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ on:
33
pull_request:
44
push:
55

6+
permissions:
7+
contents: read # to fetch code (actions/checkout)
8+
69
jobs:
710
test:
811
strategy:
@@ -41,15 +44,15 @@ jobs:
4144
java: 8
4245
distribution: adopt
4346
jobtype: 8
44-
- os: windows-2019
47+
- os: windows-latest
4548
java: 8
4649
distribution: adopt
4750
jobtype: 9
4851
runs-on: ${{ matrix.os }}
4952
env:
5053
JAVA_OPTS: -Xms800M -Xmx2G -Xss6M -XX:ReservedCodeCacheSize=128M -server -Dsbt.io.virtual=false -Dfile.encoding=UTF-8
5154
JVM_OPTS: -Xms800M -Xmx2G -Xss6M -XX:ReservedCodeCacheSize=128M -server -Dsbt.io.virtual=false -Dfile.encoding=UTF-8
52-
SCALA_212: 2.12.16
55+
SCALA_212: 2.12.17
5356
SCALA_213: 2.13.8
5457
SCALA_3: 3.1.0
5558
UTIL_TESTS: "utilCache/test utilControl/test utilInterface/test utilLogging/test utilPosition/test utilRelation/test utilScripted/test utilTracking/test"
@@ -97,11 +100,12 @@ jobs:
97100
key: ${{ runner.os }}-sbt-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }}
98101
- name: Setup Windows C++ toolchain
99102
uses: ilammy/msvc-dev-cmd@v1
100-
if: ${{ matrix.os == 'windows-2019' }}
103+
if: ${{ matrix.os == 'windows-latest' }}
101104
- name: Build and test (1)
102105
if: ${{ matrix.jobtype == 1 }}
103106
shell: bash
104107
run: |
108+
rm -rf "$HOME/.sbt/boot/" || true
105109
# ./sbt -v --client mimaReportBinaryIssues
106110
./sbt -v --client javafmtCheck
107111
./sbt -v --client "Test/javafmtCheck"

.github/workflows/dependency-graph.yml

+4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ name: Submit Dependency Graph
33
on:
44
push:
55
branches: [1.7.x] # default branch of the project
6+
permissions: {}
67
jobs:
78
submit-graph:
9+
permissions:
10+
contents: write # to submit the dependency graph
11+
812
name: Submit Dependency Graph
913
runs-on: ubuntu-latest # or windows-latest, or macOS-latest
1014
steps:

.github/workflows/nightly.yml

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ on:
55
# # 08:00 UTC = 03:00 EST
66
# - cron: '0 8 * * *'
77

8+
permissions:
9+
contents: read # to fetch code (actions/checkout)
10+
811
jobs:
912
deploy:
1013
strategy:

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ npm-debug.log
1414
.vscode/
1515
metals.sbt
1616
launcher-package/citest/freshly-baked
17+
.vscode

DEVELOPING.md

+7-4
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ Create a [fork](https://docs.github.com/en/github/getting-started-with-github/fo
77

88
### Branch to work against
99

10-
sbt uses two branches for development:
10+
sbt uses **two or three** branches for development:
11+
Generally the default branch set on Github is what we recommend as the base line for PRs.
1112

12-
- Development branch: `develop` (this is also called "master")
13-
- Stable branch: `1.$MINOR.x`, where `$MINOR` is current minor version (e.g. `1.1.x` during 1.1.x series)
13+
- Next minor branch: `1.$MINOR.x`, where `$MINOR` is next minor version (e.g. `1.9.x` during 1.8.x series)
14+
- Development branch: `develop`
15+
- Stable branch: `1.$MINOR.x`, where `$MINOR` is current minor version (e.g. `1.8.x` during 1.8.x series)
1416

15-
The `develop` branch represents the next major version of sbt. Only new features are pushed to the `develop` branch. This is the branch that you will branch off of to make your changes.
17+
Currently `develop` branch represents the next major version of sbt, i.e. sbt 2.
18+
Next minor branch is where new features can be added as long as it is binary compatible with sbt 1.0.
1619
The `stable` branch represents the current stable sbt release. Only bug fixes are back-ported to the stable branch.
1720

1821
### Instruction to build just sbt

build.sbt

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import scala.util.Try
1010
// ThisBuild settings take lower precedence,
1111
// but can be shared across the multi projects.
1212
ThisBuild / version := {
13-
val v = "1.7.2-SNAPSHOT"
13+
val v = "1.8.1-SNAPSHOT"
1414
nightlyVersion.getOrElse(v)
1515
}
1616
ThisBuild / version2_13 := "2.0.0-SNAPSHOT"
@@ -43,10 +43,11 @@ ThisBuild / scmInfo := Some(
4343
ScmInfo(url("https://github.com/sbt/sbt"), "[email protected]:sbt/sbt.git")
4444
)
4545
ThisBuild / resolvers += Resolver.mavenLocal
46+
ThisBuild / libraryDependencySchemes += "org.scala-lang.modules" %% "scala-xml" % VersionScheme.Always
4647

4748
Global / semanticdbEnabled := !(Global / insideCI).value
4849
// Change main/src/main/scala/sbt/plugins/SemanticdbPlugin.scala too, if you change this.
49-
Global / semanticdbVersion := "4.5.9"
50+
Global / semanticdbVersion := "4.5.13"
5051
val excludeLint = SettingKey[Set[Def.KeyedInitialize[_]]]("excludeLintKeys")
5152
Global / excludeLint := (Global / excludeLint).?.value.getOrElse(Set.empty)
5253
Global / excludeLint += componentID

internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala

+18-5
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,12 @@ object ConsoleAppender {
126126
def out: ConsoleOut
127127
}
128128
private[sbt] object Properties {
129-
def from(terminal: Terminal): Properties = new Properties {
130-
override def isAnsiSupported: Boolean = terminal.isAnsiSupported
131-
override def isColorEnabled: Boolean = terminal.isColorEnabled
132-
override def out = ConsoleOut.terminalOut(terminal)
133-
}
129+
def from(terminal: Terminal): Properties =
130+
from(ConsoleOut.terminalOut(terminal), terminal.isAnsiSupported, terminal.isColorEnabled)
131+
132+
def safelyFrom(terminal: Terminal): Properties =
133+
from(ConsoleOut.safeTerminalOut(terminal), terminal.isAnsiSupported, terminal.isColorEnabled)
134+
134135
def from(o: ConsoleOut, ansi: Boolean, color: Boolean): Properties = new Properties {
135136
override def isAnsiSupported: Boolean = ansi
136137
override def isColorEnabled: Boolean = color
@@ -246,6 +247,18 @@ object ConsoleAppender {
246247
new ConsoleAppender(name, Properties.from(terminal), noSuppressedMessage)
247248
}
248249

250+
/**
251+
* A new `ConsoleAppender` identified by `name`, and that writes to `terminal`.
252+
* Printing to this Appender will not throw if the Terminal has been closed.
253+
*
254+
* @param name An identifier for the `ConsoleAppender`.
255+
* @param terminal The terminal to which this appender corresponds
256+
* @return A new `ConsoleAppender` that writes to `terminal`.
257+
*/
258+
def safe(name: String, terminal: Terminal): Appender = {
259+
new ConsoleAppender(name, Properties.safelyFrom(terminal), noSuppressedMessage)
260+
}
261+
249262
/**
250263
* A new `ConsoleAppender` identified by `name`, and that writes to `out`.
251264
*

internal/util-logging/src/main/scala/sbt/internal/util/ConsoleOut.scala

+21
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package sbt.internal.util
99

1010
import java.io.{ BufferedWriter, PrintStream, PrintWriter }
11+
import java.nio.channels.ClosedChannelException
1112
import java.util.concurrent.ConcurrentHashMap
1213
import java.util.concurrent.atomic.AtomicReference
1314

@@ -90,6 +91,26 @@ object ConsoleOut {
9091
override def toString: String = s"TerminalOut"
9192
}
9293

94+
/** Same as terminalOut but it catches and ignores the ClosedChannelException
95+
*/
96+
def safeTerminalOut(terminal: Terminal): ConsoleOut = {
97+
val out = terminalOut(terminal)
98+
new ConsoleOut {
99+
override val lockObject: AnyRef = terminal
100+
override def print(s: String): Unit = catchException(out.print(s))
101+
override def println(s: String): Unit = catchException(out.println(s))
102+
override def println(): Unit = catchException(out.println())
103+
override def flush(): Unit = catchException(out.flush)
104+
override def toString: String = s"SafeTerminalOut($terminal)"
105+
private def catchException(f: => Unit): Unit = {
106+
try f
107+
catch {
108+
case _: ClosedChannelException => ()
109+
}
110+
}
111+
}
112+
}
113+
93114
private[this] val consoleOutPerTerminal = new ConcurrentHashMap[Terminal, ConsoleOut]
94115
def terminalOut(terminal: Terminal): ConsoleOut = consoleOutPerTerminal.get(terminal) match {
95116
case null =>

internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala

+1
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ object Terminal {
438438
override def toString: String = s"ProxyTerminal(current = $t)"
439439
}
440440
private[sbt] def get: Terminal = ProxyTerminal
441+
private[sbt] def current: Terminal = activeTerminal.get
441442

442443
private[sbt] def withIn[T](in: InputStream)(f: => T): T = {
443444
val original = inputStream.get

internal/util-logging/src/main/scala/sbt/util/LoggerContext.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ object LoggerContext {
103103
}
104104
}
105105
def close(): Unit = {
106-
loggers.forEach((name, l) => l.clearAppenders())
106+
closed.set(true)
107+
loggers.forEach((_, l) => l.clearAppenders())
107108
loggers.clear()
108109
}
109110
}

main/src/main/scala/sbt/Defaults.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,7 @@ object Defaults extends BuildCommon {
12171217
Seq(
12181218
testFrameworks :== {
12191219
import sbt.TestFrameworks._
1220-
Seq(ScalaCheck, Specs2, Specs, ScalaTest, JUnit, MUnit)
1220+
Seq(ScalaCheck, Specs2, Specs, ScalaTest, JUnit, MUnit, ZIOTest)
12211221
},
12221222
testListeners :== Nil,
12231223
testOptions :== Nil,

main/src/main/scala/sbt/PluginCross.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ private[sbt] object PluginCross {
9999
VersionNumber(sv) match {
100100
case VersionNumber(Seq(0, 12, _*), _, _) => "2.9.2"
101101
case VersionNumber(Seq(0, 13, _*), _, _) => "2.10.7"
102-
case VersionNumber(Seq(1, 0, _*), _, _) => "2.12.16"
102+
case VersionNumber(Seq(1, 0, _*), _, _) => "2.12.17"
103103
case _ => sys.error(s"Unsupported sbt binary version: $sv")
104104
}
105105
}

main/src/main/scala/sbt/coursierint/LMCoursier.scala

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import lmcoursier.definitions.{
2020
Strict => CStrict,
2121
}
2222
import lmcoursier._
23+
import lmcoursier.syntax._
2324
import lmcoursier.credentials.Credentials
2425
import Keys._
2526
import sbt.internal.util.Util

main/src/main/scala/sbt/internal/DefaultBackgroundJobService.scala

+4-11
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ private[sbt] abstract class AbstractJobHandle extends JobHandle {
7474
private[sbt] abstract class AbstractBackgroundJobService extends BackgroundJobService {
7575
private val nextId = new AtomicLong(1)
7676
private val pool = new BackgroundThreadPool()
77+
private val context = LoggerContext()
7778

7879
private[sbt] def serviceTempDirBase: File
7980
private[sbt] def useLog4J: Boolean
@@ -90,7 +91,6 @@ private[sbt] abstract class AbstractBackgroundJobService extends BackgroundJobSe
9091
// hooks for sending start/stop events
9192
protected def onAddJob(@deprecated("unused", "") job: JobHandle): Unit = ()
9293
protected def onRemoveJob(@deprecated("unused", "") job: JobHandle): Unit = ()
93-
private val context = LoggerContext()
9494

9595
// this mutable state could conceptually go on State except
9696
// that then every task that runs a background job would have
@@ -122,12 +122,9 @@ private[sbt] abstract class AbstractBackgroundJobService extends BackgroundJobSe
122122
def humanReadableName: String = job.humanReadableName
123123

124124
job.onStop { () =>
125-
// TODO: Fix this
126-
// logger.close()
127125
removeJob(this)
128126
IO.delete(workingDirectory)
129127
context.clearAppenders(logger.name)
130-
context.close()
131128
}
132129
addJob(this)
133130
override final def equals(other: Any): Boolean = other match {
@@ -144,15 +141,15 @@ private[sbt] abstract class AbstractBackgroundJobService extends BackgroundJobSe
144141
override val spawningTask: ScopedKey[_] = unknownTask
145142
}
146143

147-
protected def makeContext(id: Long, spawningTask: ScopedKey[_], state: State): ManagedLogger
148-
149144
def doRunInBackground(
150145
spawningTask: ScopedKey[_],
151146
state: State,
152147
start: (Logger, File) => BackgroundJob
153148
): JobHandle = {
154149
val id = nextId.getAndIncrement()
155-
val logger = makeContext(id, spawningTask, state)
150+
val extracted = Project.extract(state)
151+
val logger =
152+
LogManager.constructBackgroundLog(extracted.structure.data, state, context)(spawningTask)
156153
val workingDir = serviceTempDir / s"job-$id"
157154
IO.createDirectory(workingDir)
158155
val job = try {
@@ -502,10 +499,6 @@ private[sbt] class DefaultBackgroundJobService(
502499
) extends AbstractBackgroundJobService {
503500
@deprecated("Use the constructor that specifies the background job temporary directory", "1.4.0")
504501
def this() = this(IO.createTemporaryDirectory, false)
505-
override def makeContext(id: Long, spawningTask: ScopedKey[_], state: State): ManagedLogger = {
506-
val extracted = Project.extract(state)
507-
LogManager.constructBackgroundLog(extracted.structure.data, state)(spawningTask)
508-
}
509502
}
510503
private[sbt] object DefaultBackgroundJobService {
511504

main/src/main/scala/sbt/internal/LogManager.scala

+11-3
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,23 @@ object LogManager {
7272
manager(data, state, task, to, context)
7373
}
7474

75-
@nowarn
75+
@deprecated("Use alternate constructBackgroundLog that provides a LoggerContext", "1.8.0")
7676
def constructBackgroundLog(
7777
data: Settings[Scope],
7878
state: State
79+
): ScopedKey[_] => ManagedLogger = {
80+
val context = state.get(Keys.loggerContext).getOrElse(LoggerContext.globalContext)
81+
constructBackgroundLog(data, state, context)
82+
}
83+
84+
def constructBackgroundLog(
85+
data: Settings[Scope],
86+
state: State,
87+
context: LoggerContext
7988
): (ScopedKey[_]) => ManagedLogger =
8089
(task: ScopedKey[_]) => {
8190
val manager: LogManager =
8291
(logManager in task.scope).get(data) getOrElse defaultManager(state.globalLogging.console)
83-
val context = state.get(Keys.loggerContext).getOrElse(LoggerContext.globalContext)
8492
manager.backgroundLog(data, state, task, context)
8593
}
8694

@@ -134,7 +142,7 @@ object LogManager {
134142
task: ScopedKey[_],
135143
context: LoggerContext
136144
): ManagedLogger = {
137-
val console = screen(task, state)
145+
val console = ConsoleAppender.safe("bg-" + ConsoleAppender.generateName(), ITerminal.current)
138146
LogManager.backgroundLog(data, state, task, console, relay(()), context)
139147
}
140148
}

main/src/main/scala/sbt/internal/SysProp.scala

+11-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import java.util.Locale
1414

1515
import scala.util.control.NonFatal
1616
import scala.concurrent.duration._
17+
import sbt.internal.inc.HashUtil
1718
import sbt.internal.util.{ Terminal => ITerminal, Util }
1819
import sbt.internal.util.complete.SizeParser
1920
import sbt.io.syntax._
@@ -247,7 +248,15 @@ object SysProp {
247248
* Windows, and Docker environment.
248249
* Mostly these directories will be used as throw-away location to extract
249250
* native files etc.
251+
* A deterministic hash is appended in the directory name as "/tmp/.sbt1234ABCD/"
252+
* to avoid collision between multiple users in a shared server environment.
250253
*/
251-
private[this] def runtimeDirectory: Path =
252-
Paths.get(sys.env.getOrElse("XDG_RUNTIME_DIR", sys.props("java.io.tmpdir"))).resolve(".sbt")
254+
private[this] def runtimeDirectory: Path = {
255+
val hashValue =
256+
java.lang.Long.toHexString(HashUtil.farmHash(home.toString.getBytes("UTF-8")))
257+
val halfhash = hashValue.take(8)
258+
Paths
259+
.get(sys.env.getOrElse("XDG_RUNTIME_DIR", sys.props("java.io.tmpdir")))
260+
.resolve(s".sbt$halfhash")
261+
}
253262
}

main/src/main/scala/sbt/internal/server/BuildServerReporter.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ final class BuildServerReporterImpl(
201201
Diagnostic(
202202
range,
203203
Option(toDiagnosticSeverity(problem.severity)),
204-
None,
204+
problem.diagnosticCode().toOption.map(_.code),
205205
Option("sbt"),
206206
problem.message
207207
)

main/src/main/scala/sbt/plugins/Giter8TemplatePlugin.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ object Giter8TemplatePlugin extends AutoPlugin {
2626
ModuleID(
2727
"org.scala-sbt.sbt-giter8-resolver",
2828
"sbt-giter8-resolver",
29-
"0.13.1"
29+
"0.15.0"
3030
) cross CrossVersion.binary,
3131
"sbtgiter8resolver.Giter8TemplateResolver"
3232
)

main/src/main/scala/sbt/plugins/SemanticdbPlugin.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ object SemanticdbPlugin extends AutoPlugin {
2626
semanticdbEnabled := SysProp.semanticdb,
2727
semanticdbIncludeInJar := false,
2828
semanticdbOptions := List(),
29-
semanticdbVersion := "4.5.9"
29+
semanticdbVersion := "4.5.13"
3030
)
3131

3232
override lazy val projectSettings: Seq[Def.Setting[_]] = Seq(

0 commit comments

Comments
 (0)