Skip to content

Commit 34a3a93

Browse files
ivan-klassmajk-ptgodzik
authored
Support links in using file directive (implements #1328) (#3681)
* Support links in using file directive Co-authored-by: Michał Pawlik <[email protected]> Co-authored-by: tgodzik <[email protected]> * remove git+ssh, add remote example * scalafix & updated docs * New error class for Uri file errors * Pass downloader directly * add using file link test --------- Co-authored-by: Michał Pawlik <[email protected]> Co-authored-by: tgodzik <[email protected]>
1 parent fca505b commit 34a3a93

File tree

19 files changed

+131
-42
lines changed

19 files changed

+131
-42
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,8 @@ object Build {
267267
),
268268
logger,
269269
options.suppressWarningOptions,
270-
options.internal.exclude
270+
options.internal.exclude,
271+
download = options.downloader
271272
)
272273

273274
private def build(

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

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import scala.build.errors.{
77
CompositeBuildException,
88
ExcludeDefinitionError,
99
MalformedDirectiveError,
10-
Severity
10+
Severity,
11+
UsingFileFromUriError
1112
}
1213
import scala.build.input.*
1314
import scala.build.input.ElementsUtils.*
@@ -156,7 +157,8 @@ object CrossSources {
156157
logger: Logger,
157158
suppressWarningOptions: SuppressWarningOptions,
158159
exclude: Seq[Positioned[String]] = Nil,
159-
maybeRecoverOnError: BuildException => Option[BuildException] = e => Some(e)
160+
maybeRecoverOnError: BuildException => Option[BuildException] = e => Some(e),
161+
download: BuildOptions.Download = BuildOptions.Download.notSupported
160162
)(using ScalaCliInvokeData): Either[BuildException, (CrossSources, Inputs)] = either {
161163

162164
def preprocessSources(elems: Seq[SingleElement])
@@ -204,8 +206,9 @@ object CrossSources {
204206
.flatMap(_.options)
205207
.flatMap(_.internal.extraSourceFiles)
206208
.distinct
207-
val inputsElemFromDirectives: Seq[SingleFile] =
208-
value(resolveInputsFromSources(sourcesFromDirectives, inputs.enableMarkdown))
209+
210+
val inputsElemFromDirectives: Seq[SingleElement] =
211+
value(resolveInputsFromSources(sourcesFromDirectives, inputs.enableMarkdown, download))
209212
val preprocessedSourcesFromDirectives: Seq[PreprocessedSource] =
210213
value(preprocessSources(inputsElemFromDirectives.pipe(elements =>
211214
value(excludeSources(elements, inputs.workspace, allExclude))
@@ -398,7 +401,32 @@ object CrossSources {
398401
fromInputs ++ fromSources ++ fromSourcesWithRequirements
399402
}
400403

401-
private def resolveInputsFromSources(sources: Seq[Positioned[os.Path]], enableMarkdown: Boolean) =
404+
private def downloadFile(download: BuildOptions.Download)(pUri: Positioned[java.net.URI]) =
405+
download(pUri.value.toString).left.map(
406+
new UsingFileFromUriError(pUri.value, pUri.positions, _)
407+
).map(content =>
408+
Seq(Virtual(pUri.value.toString, content))
409+
)
410+
411+
type CodeFile = os.Path | java.net.URI
412+
413+
private def resolveInputsFromSources(
414+
sources: Seq[Positioned[CodeFile]],
415+
enableMarkdown: Boolean,
416+
download: BuildOptions.Download
417+
) =
418+
val links = sources.collect {
419+
case Positioned(pos, value: java.net.URI) => Positioned(pos, value)
420+
}
421+
val paths = sources.collect {
422+
case Positioned(pos, value: os.Path) => Positioned(pos, value)
423+
}
424+
425+
(resolveInputsFromPath(paths, enableMarkdown) ++ links.map(downloadFile(download))).sequence
426+
.left.map(CompositeBuildException(_))
427+
.map(_.flatten)
428+
429+
private def resolveInputsFromPath(sources: Seq[Positioned[os.Path]], enableMarkdown: Boolean) =
402430
sources.map { source =>
403431
val sourcePath = source.value
404432
lazy val dir = sourcePath / os.up
@@ -419,9 +447,7 @@ object CrossSources {
419447
else s"$sourcePath: not found path defined in using directive."
420448
Left(new MalformedDirectiveError(msg, source.positions))
421449
}
422-
}.sequence
423-
.left.map(CompositeBuildException(_))
424-
.map(_.flatten)
450+
}
425451

426452
/** Filters out the sources from the input sequence based on the provided 'exclude' patterns. The
427453
* exclude patterns can be absolute paths, relative paths, or glob patterns.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ final class BspImpl(
113113
logger = persistentLogger,
114114
suppressWarningOptions = buildOptions.suppressWarningOptions,
115115
exclude = buildOptions.internal.exclude,
116-
maybeRecoverOnError = maybeRecoverOnError(Scope.Main)
116+
maybeRecoverOnError = maybeRecoverOnError(Scope.Main),
117+
download = buildOptions.downloader
117118
).left.map((_, Scope.Main))
118119
}
119120

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import scala.build.errors.{BuildException, InputsException, WorkspaceError}
1111
import scala.build.input.ElementsUtils.*
1212
import scala.build.internal.Constants
1313
import scala.build.internal.zip.WrappedZipInputStream
14-
import scala.build.options.Scope
14+
import scala.build.options.{BuildOptions, Scope}
1515
import scala.build.preprocessing.SheBang.isShebangScript
1616
import scala.util.matching.Regex
1717
import scala.util.{Properties, Try}
@@ -225,7 +225,7 @@ object Inputs {
225225
def validateArgs(
226226
args: Seq[String],
227227
cwd: os.Path,
228-
download: String => Either[String, Array[Byte]],
228+
download: BuildOptions.Download,
229229
stdinOpt: => Option[Array[Byte]],
230230
acceptFds: Boolean,
231231
enableMarkdown: Boolean
@@ -423,7 +423,7 @@ object Inputs {
423423
args: Seq[String],
424424
cwd: os.Path,
425425
defaultInputs: () => Option[Inputs] = () => None,
426-
download: String => Either[String, Array[Byte]] = _ => Left("URL not supported"),
426+
download: BuildOptions.Download = BuildOptions.Download.notSupported,
427427
stdinOpt: => Option[Array[Byte]] = None,
428428
scriptSnippetList: List[String] = List.empty,
429429
scalaSnippetList: List[String] = List.empty,

modules/cli/src/main/scala/scala/cli/commands/bsp/Bsp.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ object Bsp extends ScalaCommand[BspOptions] {
108108
),
109109
persistentLogger,
110110
baseOptions.suppressWarningOptions,
111-
baseOptions.internal.exclude
111+
baseOptions.internal.exclude,
112+
download = baseOptions.downloader
112113
)
113114

114115
val (allInputs, finalBuildOptions) = {

modules/cli/src/main/scala/scala/cli/commands/dependencyupdate/DependencyUpdate.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ object DependencyUpdate extends ScalaCommand[DependencyUpdateOptions] {
4444
),
4545
logger,
4646
buildOptions.suppressWarningOptions,
47-
buildOptions.internal.exclude
47+
buildOptions.internal.exclude,
48+
download = buildOptions.downloader
4849
).orExit(logger)
4950

5051
val sharedOptions = crossSources.sharedOptions(buildOptions)

modules/cli/src/main/scala/scala/cli/commands/export0/Export.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ object Export extends ScalaCommand[ExportOptions] {
4343
),
4444
logger,
4545
buildOptions.suppressWarningOptions,
46-
buildOptions.internal.exclude
46+
buildOptions.internal.exclude,
47+
download = buildOptions.downloader
4748
)
4849
}
4950

modules/cli/src/main/scala/scala/cli/commands/fix/BuiltInRules.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ object BuiltInRules extends CommandHelpers {
169169
),
170170
logger = logger,
171171
suppressWarningOptions = SuppressWarningOptions.suppressAll,
172-
exclude = buildOptions.internal.exclude
172+
exclude = buildOptions.internal.exclude,
173+
download = buildOptions.downloader
173174
).orExit(logger)
174175

175176
val sharedOptions = crossSources.sharedOptions(buildOptions)

modules/cli/src/main/scala/scala/cli/commands/publish/PublishSetup.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ object PublishSetup extends ScalaCommand[PublishSetupOptions] {
8989
),
9090
logger,
9191
cliBuildOptions.suppressWarningOptions,
92-
cliBuildOptions.internal.exclude
92+
cliBuildOptions.internal.exclude,
93+
download = cliBuildOptions.downloader
9394
).orExit(logger)
9495

9596
val crossSourcesSharedOptions = crossSources.sharedOptions(cliBuildOptions)

modules/cli/src/main/scala/scala/cli/commands/setupide/SetupIde.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ object SetupIde extends ScalaCommand[SetupIdeOptions] {
4343
),
4444
logger,
4545
options.suppressWarningOptions,
46-
options.internal.exclude
46+
options.internal.exclude,
47+
download = options.downloader
4748
)
4849
}
4950

0 commit comments

Comments
 (0)