Skip to content

Commit a963ed0

Browse files
authored
Merge pull request #943 from Gedochao/refactor-main-class-override
Refactor the usage of default main class override to only apply to on-disk Scripts
2 parents 47f6cf5 + 6f680d2 commit a963ed0

File tree

11 files changed

+71
-83
lines changed

11 files changed

+71
-83
lines changed

modules/build/src/main/scala/scala/build/Build.scala

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ import java.io.File
99
import java.nio.file.{FileSystemException, Path}
1010
import java.util.concurrent.{ScheduledExecutorService, ScheduledFuture}
1111

12+
import scala.annotation.tailrec
1213
import scala.build.EitherCps.{either, value}
13-
import scala.build.Ops._
14+
import scala.build.Ops.*
1415
import scala.build.compiler.{ScalaCompiler, ScalaCompilerMaker}
15-
import scala.build.errors._
16+
import scala.build.errors.*
1617
import scala.build.internal.{Constants, CustomCodeWrapper, MainClass, Util}
17-
import scala.build.options._
18+
import scala.build.options.*
1819
import scala.build.options.validation.ValidationException
19-
import scala.build.postprocessing._
20+
import scala.build.postprocessing.*
2021
import scala.collection.mutable.ListBuffer
2122
import scala.concurrent.duration.DurationInt
2223
import scala.util.Properties
@@ -57,7 +58,7 @@ object Build {
5758
MainClass.find(output)
5859
def retainedMainClass: Either[MainClassError, String] = {
5960
lazy val foundMainClasses0 = foundMainClasses()
60-
val defaultMainClassOpt = sources.mainClass
61+
val defaultMainClassOpt = sources.defaultMainClass
6162
.filter(name => foundMainClasses0.contains(name))
6263
def foundMainClass =
6364
if (foundMainClasses0.isEmpty) Left(new NoMainClassFoundError)
@@ -329,7 +330,7 @@ object Build {
329330
builds
330331
}
331332

332-
private def copyResourceToClassesDir(build: Build) = build match {
333+
private def copyResourceToClassesDir(build: Build): Unit = build match {
333334
case b: Build.Successful =>
334335
for {
335336
resourceDirPath <- b.sources.resourceDirs.filter(os.exists(_))
@@ -502,7 +503,7 @@ object Build {
502503
logger: Logger,
503504
options: BuildOptions
504505
): Either[BuildException, Unit] = {
505-
val (errors, otherDiagnostics) = options.validate.toSeq.partition(_.severity == Severity.Error)
506+
val (errors, otherDiagnostics) = options.validate.partition(_.severity == Severity.Error)
506507
logger.log(otherDiagnostics)
507508
if (errors.nonEmpty)
508509
Left(CompositeBuildException(errors.map(new ValidationException(_))))
@@ -541,7 +542,7 @@ object Build {
541542
logger
542543
))
543544

544-
def run() = {
545+
def run(): Unit = {
545546
try {
546547
val res = build(
547548
inputs,
@@ -940,6 +941,7 @@ object Build {
940941
def onError(t: Throwable): Unit = {
941942
// TODO Log that properly
942943
System.err.println("got error:")
944+
@tailrec
943945
def printEx(t: Throwable): Unit =
944946
if (t != null) {
945947
System.err.println(t)
@@ -973,7 +975,7 @@ object Build {
973975
}
974976

975977
private val lock = new Object
976-
private var f: ScheduledFuture[_] = null
978+
private var f: ScheduledFuture[?] = _
977979
private val waitFor = 50.millis
978980
private val runnable: Runnable = { () =>
979981
lock.synchronized {
@@ -1080,7 +1082,7 @@ object Build {
10801082
command.iterator.map(_ + System.lineSeparator()).mkString
10811083
)
10821084

1083-
new ProcessBuilder(command: _*)
1085+
new ProcessBuilder(command*)
10841086
.inheritIO()
10851087
.start()
10861088
.waitFor()

modules/build/src/main/scala/scala/build/CrossSources.scala

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package scala.build
22

33
import scala.build.EitherCps.{either, value}
4-
import scala.build.Ops._
4+
import scala.build.Ops.*
55
import scala.build.errors.{BuildException, CompositeBuildException}
66
import scala.build.options.{BuildOptions, BuildRequirements, HasBuildRequirements, Scope}
7-
import scala.build.preprocessing._
7+
import scala.build.preprocessing.*
88

99
final case class CrossSources(
1010
paths: Seq[HasBuildRequirements[(os.Path, os.RelPath)]],
1111
inMemory: Seq[HasBuildRequirements[Sources.InMemory]],
12-
mainClass: Option[String],
12+
defaultMainClass: Option[String],
1313
resourceDirs: Seq[HasBuildRequirements[os.Path]],
1414
buildOptions: Seq[HasBuildRequirements[BuildOptions]]
1515
) {
@@ -49,7 +49,7 @@ final case class CrossSources(
4949
.flatMap(_.withScalaVersion(retainedScalaVersion).toSeq)
5050
.flatMap(_.withPlatform(platform.value).toSeq)
5151
.map(_.scopedValue(defaultScope)),
52-
mainClass,
52+
defaultMainClass,
5353
resourceDirs
5454
.flatMap(_.withScalaVersion(retainedScalaVersion).toSeq)
5555
.flatMap(_.withPlatform(platform.value).toSeq)
@@ -132,11 +132,8 @@ object CrossSources {
132132
)
133133
}
134134

135-
val mainClassOpt = for {
136-
mainClassPath <- inputs.mainClassElement.map {
137-
case sf: Inputs.SourceFile => ScopePath.fromPath(sf.path).path
138-
case vsf: Inputs.VirtualScalaFile => vsf.scopePath.path
139-
}
135+
val defaultMainClassOpt = for {
136+
mainClassPath <- inputs.defaultMainClassElement.map(s => ScopePath.fromPath(s.path).path)
140137
processedMainClass <- preprocessedSources.find(_.scopePath.path == mainClassPath)
141138
mainClass <- processedMainClass.mainClassOpt
142139
} yield mainClass
@@ -165,6 +162,6 @@ object CrossSources {
165162
HasBuildRequirements(BuildRequirements(), _)
166163
)
167164

168-
CrossSources(paths, inMemory, mainClassOpt, resourceDirs, buildOptions)
165+
CrossSources(paths, inMemory, defaultMainClassOpt, resourceDirs, buildOptions)
169166
}
170167
}

modules/build/src/main/scala/scala/build/Inputs.scala

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import scala.util.matching.Regex
1616

1717
final case class Inputs(
1818
elements: Seq[Inputs.Element],
19-
mainClassElement: Option[Inputs.SingleElement],
19+
defaultMainClassElement: Option[Inputs.Script],
2020
workspace: os.Path,
2121
baseProjectName: String,
2222
mayAppendHash: Boolean,
@@ -57,7 +57,7 @@ final case class Inputs(
5757

5858
private lazy val inputsHash: String =
5959
Inputs.inputsHash(elements)
60-
lazy val projectName = {
60+
lazy val projectName: String = {
6161
val needsSuffix = mayAppendHash && (elements match {
6262
case Seq(d: Inputs.Directory) => d.path != workspace
6363
case _ => true
@@ -87,19 +87,18 @@ final case class Inputs(
8787
if (forbidden.exists(workspace.startsWith)) inHomeDir(directories)
8888
else this
8989
def checkAttributes(directories: Directories): Inputs = {
90+
@tailrec
9091
def existingParent(p: os.Path): Option[os.Path] =
9192
if (os.exists(p)) Some(p)
9293
else if (p.segmentCount <= 0) None
9394
else existingParent(p / os.up)
9495
def reallyOwnedByUser(p: os.Path): Boolean =
9596
if (Properties.isWin)
96-
p.toIO.canWrite() // Wondering if there's a better way to do that…
97+
p.toIO.canWrite // Wondering if there's a better way to do that…
9798
else
9899
os.owner(p) == os.owner(os.home) &&
99-
p.toIO.canWrite()
100-
val canWrite = existingParent(workspace)
101-
.map(reallyOwnedByUser)
102-
.getOrElse(false)
100+
p.toIO.canWrite
101+
val canWrite = existingParent(workspace).exists(reallyOwnedByUser)
103102
if (canWrite) this
104103
else inHomeDir(directories)
105104
}
@@ -123,7 +122,7 @@ final case class Inputs(
123122
Iterator(v.content, bytes("\n"))
124123
}
125124
val md = MessageDigest.getInstance("SHA-1")
126-
it.foreach(md.update(_))
125+
it.foreach(md.update)
127126
val digest = md.digest()
128127
val calculatedSum = new BigInteger(1, digest)
129128
String.format(s"%040x", calculatedSum)
@@ -188,15 +187,15 @@ object Inputs {
188187

189188
final case class Script(base: os.Path, subPath: os.SubPath)
190189
extends OnDisk with SourceFile with AnyScalaFile with AnyScript {
191-
lazy val path = base / subPath
190+
lazy val path: os.Path = base / subPath
192191
}
193192
final case class ScalaFile(base: os.Path, subPath: os.SubPath)
194193
extends OnDisk with SourceFile with AnyScalaFile {
195-
lazy val path = base / subPath
194+
lazy val path: os.Path = base / subPath
196195
}
197196
final case class JavaFile(base: os.Path, subPath: os.SubPath)
198197
extends OnDisk with SourceFile with Compiled {
199-
lazy val path = base / subPath
198+
lazy val path: os.Path = base / subPath
200199
}
201200
final case class Directory(path: os.Path) extends OnDisk with Compiled
202201
final case class ResourceDirectory(path: os.Path) extends OnDisk
@@ -226,13 +225,13 @@ object Inputs {
226225
Iterator(bytes("virtual:"), v.content, bytes("\n"))
227226
}
228227
val md = MessageDigest.getInstance("SHA-1")
229-
it.foreach(md.update(_))
228+
it.foreach(md.update)
230229
val digest = md.digest()
231230
val calculatedSum = new BigInteger(1, digest)
232231
String.format(s"%040x", calculatedSum).take(10)
233232
}
234233

235-
def homeWorkspace(elements: Seq[Element], directories: Directories) = {
234+
def homeWorkspace(elements: Seq[Element], directories: Directories): os.Path = {
236235
val hash0 = inputsHash(elements)
237236
val dir = directories.virtualProjectsDir / hash0.take(2) / s"project-${hash0.drop(2)}"
238237
os.makeDir.all(dir)
@@ -279,14 +278,11 @@ object Inputs {
279278
case _: ResourceDirectory => true
280279
case _: Virtual => true
281280
}
282-
val mainClassElemOpt = validElems
283-
.collectFirst {
284-
case f: SourceFile => f
285-
case vsf: VirtualScalaFile => vsf
286-
}
281+
// only on-disk scripts need a main class override
282+
val defaultMainClassElemOpt = validElems.collectFirst { case script: Script => script }
287283
Inputs(
288284
updatedElems,
289-
mainClassElemOpt,
285+
defaultMainClassElemOpt,
290286
workspace,
291287
baseProjectName,
292288
mayAppendHash = needsHash,
@@ -295,23 +291,22 @@ object Inputs {
295291
}
296292

297293
private val githubGistsArchiveRegex: Regex =
298-
s""":\\/\\/gist\\.github\\.com\\/[^\\/]*?\\/[^\\/]*$$""".r
299-
300-
private def resolve(path: String, content: Array[Byte]): Element = {
301-
val wrapperPath =
302-
os.sub / path.split("/").last
294+
s"""://gist\\.github\\.com/[^/]*?/[^/]*$$""".r
303295

296+
private def resolve(path: String, content: Array[Byte]): Element =
304297
if (path.endsWith(".scala")) VirtualScalaFile(content, path)
305298
else if (path.endsWith(".java")) VirtualJavaFile(content, path)
306-
else if (path.endsWith(".sc")) VirtualScript(content, path, wrapperPath)
299+
else if (path.endsWith(".sc")) {
300+
val wrapperPath = os.sub / path.split("/").last
301+
VirtualScript(content, path, wrapperPath)
302+
}
307303
else VirtualData(content, path)
308-
}
309304

310305
private def resolveZipArchive(content: Array[Byte]): Seq[Element] = {
311306
val zipInputStream = new ZipInputStream(new ByteArrayInputStream(content))
312307
@tailrec
313308
def readArchive(acc: Seq[Element]): Seq[Element] =
314-
Option(zipInputStream.getNextEntry()) match {
309+
Option(zipInputStream.getNextEntry) match {
315310
case Some(entry) if entry.isDirectory => readArchive(acc)
316311
case Some(entry) =>
317312
val content = zipInputStream.readAllBytes()
@@ -429,7 +424,7 @@ object Inputs {
429424
def empty(workspace: os.Path): Inputs =
430425
Inputs(
431426
elements = Nil,
432-
mainClassElement = None,
427+
defaultMainClassElement = None,
433428
workspace = workspace,
434429
baseProjectName = "project",
435430
mayAppendHash = true,

modules/build/src/main/scala/scala/build/ScopedSources.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import scala.build.options.{BuildOptions, HasScope, Scope}
55
final case class ScopedSources(
66
paths: Seq[HasScope[(os.Path, os.RelPath)]],
77
inMemory: Seq[HasScope[Sources.InMemory]],
8-
mainClass: Option[String],
8+
defaultMainClass: Option[String],
99
resourceDirs: Seq[HasScope[os.Path]],
1010
buildOptions: Seq[HasScope[BuildOptions]]
1111
) {
1212
def sources(scope: Scope, baseOptions: BuildOptions): Sources =
1313
Sources(
1414
paths.flatMap(_.valueFor(scope).toSeq),
1515
inMemory.flatMap(_.valueFor(scope).toSeq),
16-
mainClass,
16+
defaultMainClass,
1717
resourceDirs.flatMap(_.valueFor(scope).toSeq),
1818
buildOptions
1919
.flatMap(_.valueFor(scope).toSeq)

modules/build/src/main/scala/scala/build/Sources.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ package scala.build
22

33
import scala.build.internal.CodeWrapper
44
import scala.build.options.{BuildOptions, Scope}
5-
import scala.build.preprocessing._
5+
import scala.build.preprocessing.*
66

77
final case class Sources(
88
paths: Seq[(os.Path, os.RelPath)],
99
inMemory: Seq[Sources.InMemory],
10-
mainClass: Option[String],
10+
defaultMainClass: Option[String],
1111
resourceDirs: Seq[os.Path],
1212
buildOptions: BuildOptions
1313
) {

modules/build/src/main/scala/scala/build/internal/NativeBuilderHelper.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ object NativeBuilderHelper {
4949
dest: os.Path,
5050
nativeWorkDir: os.Path,
5151
currentProjectSha: String
52-
) = {
52+
): Unit = {
5353
val projectShaPath = resolveProjectShaPath(nativeWorkDir)
5454
os.write.over(projectShaPath, currentProjectSha, createFolders = true)
5555

0 commit comments

Comments
 (0)