Skip to content

Commit c8f4974

Browse files
committed
Add computing version for BuildInfo
1 parent 5966f65 commit c8f4974

File tree

25 files changed

+326
-135
lines changed

25 files changed

+326
-135
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -269,10 +269,10 @@ object Build {
269269

270270
val scopedSources = value(crossSources.scopedSources(baseOptions))
271271

272-
val mainSources = scopedSources.sources(Scope.Main, baseOptions)
272+
val mainSources = value(scopedSources.sources(Scope.Main, baseOptions, allInputs.workspace))
273273
val mainOptions = mainSources.buildOptions
274274

275-
val testSources = scopedSources.sources(Scope.Test, baseOptions)
275+
val testSources = value(scopedSources.sources(Scope.Test, baseOptions, allInputs.workspace))
276276
val testOptions = testSources.buildOptions
277277

278278
val inputs0 = updateInputs(

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

+35-23
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package scala.build
22

33
import java.nio.charset.StandardCharsets
44

5+
import scala.build.EitherCps.{either, value}
6+
import scala.build.errors.BuildException
57
import scala.build.info.{BuildInfo, ScopedBuildInfo}
68
import scala.build.options.{BuildOptions, HasScope, Scope}
79
import scala.build.preprocessing.ScriptPreprocessor
@@ -50,7 +52,11 @@ final case class ScopedSources(
5052
* @return
5153
* [[Sources]] instance that belong to specified scope
5254
*/
53-
def sources(scope: Scope, baseOptions: BuildOptions): Sources =
55+
def sources(
56+
scope: Scope,
57+
baseOptions: BuildOptions,
58+
workspace: os.Path
59+
): Either[BuildException, Sources] = either {
5460
val combinedOptions = combinedBuildOptions(scope, baseOptions)
5561

5662
val codeWrapper = ScriptPreprocessor.getScriptWrapper(combinedOptions)
@@ -62,12 +68,16 @@ final case class ScopedSources(
6268
val needsBuildInfo = combinedOptions.sourceGeneratorOptions.useBuildInfo.getOrElse(false)
6369

6470
val maybeBuildInfoSource = if (needsBuildInfo && scope == Scope.Main)
65-
Seq(Sources.InMemory(
66-
Left("build-info"),
67-
os.rel / "BuildInfo.scala",
68-
buildInfo(combinedOptions).generateContents().getBytes(StandardCharsets.UTF_8),
69-
None
70-
))
71+
Seq(
72+
Sources.InMemory(
73+
Left("build-info"),
74+
os.rel / "BuildInfo.scala",
75+
value(buildInfo(combinedOptions, workspace)).generateContents().getBytes(
76+
StandardCharsets.UTF_8
77+
),
78+
None
79+
)
80+
)
7181
else Nil
7282

7383
Sources(
@@ -77,6 +87,7 @@ final case class ScopedSources(
7787
resourceDirs.flatMap(_.valueFor(scope).toSeq),
7888
combinedOptions
7989
)
90+
}
8091

8192
/** Combine build options that had no requirements (console and using directives) or their
8293
* requirements have been resolved (e.g. target using directives) with build options that require
@@ -94,24 +105,25 @@ final case class ScopedSources(
94105
buildOptionsFor(scope)
95106
.foldRight(baseOptions)(_ orElse _)
96107

97-
def buildInfo(baseOptions: BuildOptions): BuildInfo = {
98-
def getScopedBuildInfo(scope: Scope): ScopedBuildInfo =
99-
val combinedOptions = combinedBuildOptions(scope, baseOptions)
100-
val sourcePaths = paths.flatMap(_.valueFor(scope).toSeq).map(_._1.toString)
101-
val inMemoryPaths =
102-
(inMemory.flatMap(_.valueFor(scope).toSeq).flatMap(_.originalPath.toOption) ++
103-
unwrappedScripts.flatMap(_.valueFor(scope).toSeq).flatMap(_.originalPath.toOption))
104-
.map(_._2.toString)
108+
def buildInfo(baseOptions: BuildOptions, workspace: os.Path): Either[BuildException, BuildInfo] =
109+
either {
110+
def getScopedBuildInfo(scope: Scope): ScopedBuildInfo =
111+
val combinedOptions = combinedBuildOptions(scope, baseOptions)
112+
val sourcePaths = paths.flatMap(_.valueFor(scope).toSeq).map(_._1.toString)
113+
val inMemoryPaths =
114+
(inMemory.flatMap(_.valueFor(scope).toSeq).flatMap(_.originalPath.toOption) ++
115+
unwrappedScripts.flatMap(_.valueFor(scope).toSeq).flatMap(_.originalPath.toOption))
116+
.map(_._2.toString)
105117

106-
ScopedBuildInfo(combinedOptions, sourcePaths ++ inMemoryPaths)
118+
ScopedBuildInfo(combinedOptions, sourcePaths ++ inMemoryPaths)
107119

108-
val baseBuildInfo = BuildInfo(combinedBuildOptions(Scope.Main, baseOptions))
120+
val baseBuildInfo = value(BuildInfo(combinedBuildOptions(Scope.Main, baseOptions), workspace))
109121

110-
val mainBuildInfo = getScopedBuildInfo(Scope.Main)
111-
val testBuildInfo = getScopedBuildInfo(Scope.Test)
122+
val mainBuildInfo = getScopedBuildInfo(Scope.Main)
123+
val testBuildInfo = getScopedBuildInfo(Scope.Test)
112124

113-
baseBuildInfo
114-
.withScope(Scope.Main.name, mainBuildInfo)
115-
.withScope(Scope.Test.name, testBuildInfo)
116-
}
125+
baseBuildInfo
126+
.withScope(Scope.Main.name, mainBuildInfo)
127+
.withScope(Scope.Test.name, testBuildInfo)
128+
}
117129
}

modules/build/src/main/scala/scala/build/bsp/BspImpl.scala

+9-4
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,15 @@ final class BspImpl(
122122
if (verbosity >= 3)
123123
pprint.err.log(scopedSources)
124124

125-
val sourcesMain =
126-
scopedSources.sources(Scope.Main, sharedOptions)
127-
val sourcesTest =
128-
scopedSources.sources(Scope.Test, sharedOptions)
125+
val sourcesMain = value {
126+
scopedSources.sources(Scope.Main, sharedOptions, allInputs.workspace)
127+
.left.map((_, Scope.Main))
128+
}
129+
130+
val sourcesTest = value {
131+
scopedSources.sources(Scope.Test, sharedOptions, allInputs.workspace)
132+
.left.map((_, Scope.Test))
133+
}
129134

130135
if (verbosity >= 3)
131136
pprint.err.log(sourcesMain)

modules/build/src/main/scala/scala/build/preprocessing/directives/DirectivesPreprocessingUtils.scala

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ object DirectivesPreprocessingUtils {
1313
val usingDirectiveHandlers: Seq[DirectiveHandler[BuildOptions]] =
1414
Seq[DirectiveHandler[_ <: HasBuildOptions]](
1515
directives.BuildInfo.handler,
16+
directives.ComputeVersion.handler,
1617
directives.Exclude.handler,
1718
directives.JavaHome.handler,
1819
directives.Jvm.handler,

modules/build/src/test/scala/scala/build/tests/ExcludeTests.scala

+16-8
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class ExcludeTests extends munit.FunSuite {
8686
os.rel / "project.scala" ->
8787
s"""//> using exclude "Main.scala" """
8888
)
89-
testInputs.withInputs { (_, inputs) =>
89+
testInputs.withInputs { (root, inputs) =>
9090
val (crossSources, _) =
9191
CrossSources.forInputs(
9292
inputs,
@@ -96,7 +96,9 @@ class ExcludeTests extends munit.FunSuite {
9696
)(using ScalaCliInvokeData.dummy).orThrow
9797
val scopedSources = crossSources.scopedSources(BuildOptions())
9898
.orThrow
99-
val sources = scopedSources.sources(Scope.Main, crossSources.sharedOptions(BuildOptions()))
99+
val sources =
100+
scopedSources.sources(Scope.Main, crossSources.sharedOptions(BuildOptions()), root)
101+
.orThrow
100102

101103
expect(sources.paths.nonEmpty)
102104
expect(sources.paths.length == 2)
@@ -113,7 +115,7 @@ class ExcludeTests extends munit.FunSuite {
113115
os.rel / "project.scala" ->
114116
s"""//> using exclude "$${.}${File.separator}Main.scala" """
115117
)
116-
testInputs.withInputs { (_, inputs) =>
118+
testInputs.withInputs { (root, inputs) =>
117119
val (crossSources, _) =
118120
CrossSources.forInputs(
119121
inputs,
@@ -123,7 +125,9 @@ class ExcludeTests extends munit.FunSuite {
123125
)(using ScalaCliInvokeData.dummy).orThrow
124126
val scopedSources = crossSources.scopedSources(BuildOptions())
125127
.orThrow
126-
val sources = scopedSources.sources(Scope.Main, crossSources.sharedOptions(BuildOptions()))
128+
val sources =
129+
scopedSources.sources(Scope.Main, crossSources.sharedOptions(BuildOptions()), root)
130+
.orThrow
127131

128132
expect(sources.paths.nonEmpty)
129133
expect(sources.paths.length == 2)
@@ -140,7 +144,7 @@ class ExcludeTests extends munit.FunSuite {
140144
os.rel / "project.scala" ->
141145
"""//> using exclude "src/*.scala" """
142146
)
143-
testInputs.withInputs { (_, inputs) =>
147+
testInputs.withInputs { (root, inputs) =>
144148
val (crossSources, _) =
145149
CrossSources.forInputs(
146150
inputs,
@@ -150,7 +154,9 @@ class ExcludeTests extends munit.FunSuite {
150154
)(using ScalaCliInvokeData.dummy).orThrow
151155
val scopedSources = crossSources.scopedSources(BuildOptions())
152156
.orThrow
153-
val sources = scopedSources.sources(Scope.Main, crossSources.sharedOptions(BuildOptions()))
157+
val sources =
158+
scopedSources.sources(Scope.Main, crossSources.sharedOptions(BuildOptions()), root)
159+
.orThrow
154160

155161
expect(sources.paths.nonEmpty)
156162
expect(sources.paths.length == 2)
@@ -167,7 +173,7 @@ class ExcludeTests extends munit.FunSuite {
167173
os.rel / "project.scala" ->
168174
"""//> using exclude "src/*.scala" """
169175
)
170-
testInputs.withInputs { (_, inputs) =>
176+
testInputs.withInputs { (root, inputs) =>
171177
val (crossSources, _) =
172178
CrossSources.forInputs(
173179
inputs,
@@ -177,7 +183,9 @@ class ExcludeTests extends munit.FunSuite {
177183
)(using ScalaCliInvokeData.dummy).orThrow
178184
val scopedSources = crossSources.scopedSources(BuildOptions())
179185
.orThrow
180-
val sources = scopedSources.sources(Scope.Main, crossSources.sharedOptions(BuildOptions()))
186+
val sources =
187+
scopedSources.sources(Scope.Main, crossSources.sharedOptions(BuildOptions()), root)
188+
.orThrow
181189

182190
expect(sources.paths.nonEmpty)
183191
expect(sources.paths.length == 2)

modules/build/src/test/scala/scala/build/tests/SourceGeneratorTests.scala

+79-45
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package scala.build.tests
33
import com.eed3si9n.expecty.Expecty.expect
44

55
import java.io.IOException
6+
import scala.Console.println
67
import scala.build.Ops.EitherThrowOps
78
import scala.build.errors.ToolkitDirectiveMissingVersionError
89
import scala.build.options.{
@@ -50,6 +51,27 @@ class SourceGeneratorTests extends munit.FunSuite {
5051
"ivy:file:.../.ivy2/local/"
5152
)
5253

54+
def initializeGit(
55+
cwd: os.Path,
56+
tag: String = "test-inputs",
57+
gitUserName: String = "testUser",
58+
gitUserEmail: String = "[email protected]"
59+
): Unit = {
60+
println(s"Initializing git in $cwd...")
61+
os.proc("git", "init").call(cwd = cwd)
62+
println(s"Setting git user.name to $gitUserName")
63+
os.proc("git", "config", "--local", "user.name", gitUserName).call(cwd = cwd)
64+
println(s"Setting git user.email to $gitUserEmail")
65+
os.proc("git", "config", "--local", "user.email", gitUserEmail).call(cwd = cwd)
66+
println(s"Adding $cwd to git...")
67+
os.proc("git", "add", ".").call(cwd = cwd)
68+
println(s"Doing an initial commit...")
69+
os.proc("git", "commit", "-m", "git init test inputs").call(cwd = cwd)
70+
println(s"Tagging as $tag...")
71+
os.proc("git", "tag", tag).call(cwd = cwd)
72+
println(s"Git initialized at $cwd")
73+
}
74+
5375
test(s"BuildInfo source generated") {
5476
val inputs = TestInputs(
5577
os.rel / "main.scala" ->
@@ -73,54 +95,61 @@ class SourceGeneratorTests extends munit.FunSuite {
7395
|""".stripMargin
7496
)
7597

76-
inputs.withBuild(baseOptions, buildThreads, bloopConfigOpt) {
77-
(root, _, maybeBuild) =>
78-
expect(maybeBuild.orThrow.success)
79-
val projectDir = os.list(root / ".scala-build").filter(
80-
_.baseName.startsWith(root.baseName + "_")
81-
)
82-
expect(projectDir.size == 1)
83-
val buildInfoPath = projectDir.head / "src_generated" / "main" / "BuildInfo.scala"
84-
expect(os.isFile(buildInfoPath))
98+
inputs.fromRoot { root =>
99+
initializeGit(root, "v1.0.0")
85100

86-
val buildInfoContent = os.read(buildInfoPath)
101+
inputs.copy(forceCwd = Some(root))
102+
.withBuild(baseOptions, buildThreads, bloopConfigOpt, skipCreatingSources = true) {
103+
(root, _, maybeBuild) =>
104+
expect(maybeBuild.orThrow.success)
105+
val projectDir = os.list(root / ".scala-build").filter(
106+
_.baseName.startsWith(root.baseName + "_")
107+
)
108+
expect(projectDir.size == 1)
109+
val buildInfoPath = projectDir.head / "src_generated" / "main" / "BuildInfo.scala"
110+
expect(os.isFile(buildInfoPath))
87111

88-
expect(normalizeResolvers(buildInfoContent) ==
89-
s"""package scala.cli.build
90-
|
91-
|object BuildInfo {
92-
| val scalaVersion = "3.2.2"
93-
| val platform = "JVM"
94-
| val jvmVersion = Some("11")
95-
| val scalaJsVersion = None
96-
| val jsEsVersion = None
97-
| val scalaNativeVersion = None
98-
| val mainClass = Some("Main")
99-
|
100-
|
101-
| object Main {
102-
| val sources = Seq("${root / "main.scala"}")
103-
| val scalacOptions = Seq("-Xasync")
104-
| val scalaCompilerPlugins = Seq("org.wartremover:wartremover_3.2.2:3.0.9")
105-
| val dependencies = Seq("com.lihaoyi:os-lib_3:0.9.1")
106-
| val resolvers = Seq("ivy:file:.../scala-cli-tests-extra-repo/local-repo/...", "https://repo1.maven.org/maven2", "ivy:file:.../.ivy2/local/")
107-
| val resourceDirs = Seq("${root / "resources"}")
108-
| val customJarsDecls = Seq("${root / "TEST1.jar"}", "${root / "TEST2.jar"}")
109-
| }
110-
|
111-
| object Test {
112-
| val sources = Nil
113-
| val scalacOptions = Nil
114-
| val scalaCompilerPlugins = Nil
115-
| val dependencies = Nil
116-
| val resolvers = Nil
117-
| val resourceDirs = Nil
118-
| val customJarsDecls = Nil
119-
| }
120-
|
121-
|}
122-
|""".stripMargin)
112+
val buildInfoContent = os.read(buildInfoPath)
113+
114+
expect(normalizeResolvers(buildInfoContent) ==
115+
s"""package scala.cli.build
116+
|
117+
|object BuildInfo {
118+
| val scalaVersion = "3.2.2"
119+
| val platform = "JVM"
120+
| val jvmVersion = Some("11")
121+
| val scalaJsVersion = None
122+
| val jsEsVersion = None
123+
| val scalaNativeVersion = None
124+
| val mainClass = Some("Main")
125+
| val projectVersion = Some("1.0.0")
126+
|
127+
|
128+
| object Main {
129+
| val sources = Seq("${root / "main.scala"}")
130+
| val scalacOptions = Seq("-Xasync")
131+
| val scalaCompilerPlugins = Seq("org.wartremover:wartremover_3.2.2:3.0.9")
132+
| val dependencies = Seq("com.lihaoyi:os-lib_3:0.9.1")
133+
| val resolvers = Seq("ivy:file:.../scala-cli-tests-extra-repo/local-repo/...", "https://repo1.maven.org/maven2", "ivy:file:.../.ivy2/local/")
134+
| val resourceDirs = Seq("${root / "resources"}")
135+
| val customJarsDecls = Seq("${root / "TEST1.jar"}", "${root / "TEST2.jar"}")
136+
| }
137+
|
138+
| object Test {
139+
| val sources = Nil
140+
| val scalacOptions = Nil
141+
| val scalaCompilerPlugins = Nil
142+
| val dependencies = Nil
143+
| val resolvers = Nil
144+
| val resourceDirs = Nil
145+
| val customJarsDecls = Nil
146+
| }
147+
|
148+
|}
149+
|""".stripMargin)
150+
}
123151
}
152+
124153
}
125154

126155
test(s"BuildInfo for native") {
@@ -171,6 +200,7 @@ class SourceGeneratorTests extends munit.FunSuite {
171200
| val jsEsVersion = None
172201
| val scalaNativeVersion = Some("0.4.6")
173202
| val mainClass = Some("Main")
203+
| val projectVersion = None
174204
|
175205
|
176206
| object Main {
@@ -212,6 +242,7 @@ class SourceGeneratorTests extends munit.FunSuite {
212242
|//> using platform scala-js
213243
|//> using jsVersion 1.13.1
214244
|//> using jsEsVersionStr es2015
245+
|//> using computeVersion "command:echo TestVersion"
215246
|
216247
|//> using buildInfo
217248
|
@@ -247,6 +278,7 @@ class SourceGeneratorTests extends munit.FunSuite {
247278
| val jsEsVersion = Some("es2015")
248279
| val scalaNativeVersion = None
249280
| val mainClass = Some("Main")
281+
| val projectVersion = Some("TestVersion")
250282
|
251283
|
252284
| object Main {
@@ -285,6 +317,7 @@ class SourceGeneratorTests extends munit.FunSuite {
285317
|//> using mainClass "Main"
286318
|//> using resourceDir ./resources
287319
|//> using jar TEST1.jar TEST2.jar
320+
|//> using computeVersion "command:echo TestVersion"
288321
|
289322
|//> using buildInfo
290323
|
@@ -320,6 +353,7 @@ class SourceGeneratorTests extends munit.FunSuite {
320353
| val jsEsVersion = None
321354
| val scalaNativeVersion = None
322355
| val mainClass = Some("Main")
356+
| val projectVersion = Some("TestVersion")
323357
|
324358
|
325359
| object Main {

0 commit comments

Comments
 (0)