Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ lazy val root: Project = Project(
).settings(
unidocProjectFilter in (ScalaUnidoc, unidoc) := inAnyProject
-- inProjects(scioRepl) -- inProjects(scioSchemas) -- inProjects(scioExamples),
run <<= run in Compile in scioRepl,
aggregate in assembly := false
).aggregate(
scioCore,
Expand Down Expand Up @@ -344,6 +345,16 @@ lazy val scioRepl: Project = Project(
Nil
)
)
).settings(
mainClass in (Compile,run) := {
if (scalaVersion.value.startsWith("2.10")) {
throw new UnsupportedOperationException(
"\n\n\tERROR: Can't start Scio REPL in SBT for scala 2.10.x. " +
"Upgrade to 2.11.x. or build REPL assembly jar.\n" +
"\tMore info https://github.com/spotify/scio/wiki/Scio-REPL\n\n")
}
Some("com.spotify.scio.repl.ScioShell")
}
).settings(
assemblyJarName in assembly := s"scio-repl-${version.value}.jar"
).dependsOn(
Expand Down
36 changes: 32 additions & 4 deletions scio-repl/src/main/scala/com/spotify/scio/repl/ScioShell.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package com.spotify.scio.repl

import scala.reflect.io.File
import scala.tools.nsc.util.ClassPath
import scala.tools.nsc.{GenericRunnerCommand, MainGenericRunner}

/**
Expand All @@ -35,19 +37,41 @@ trait BaseScioShell extends MainGenericRunner {
* @param args passed from the command line
* @return `true` if execution was successful, `false` otherwise
*/
// scalastyle:off method.length
override def process(args: Array[String]): Boolean = {
// Process command line arguments into a settings object, and use that to start the REPL.
// We ignore params we don't care about - hence error function is empty
val command = new GenericRunnerCommand(args.toList, _ => ())

// if running from the assembly, need to explicitly tell it to use java classpath
command.settings.usejavacp.value = true
command.settings.classpath.append(System.getProperty("java.class.path"))
// For scala 2.10 - usejavacp
if (scala.util.Properties.versionString.contains("2.10.")) {
command.settings.classpath.append(System.getProperty("java.class.path"))
command.settings.usejavacp.value = true
}

def classLoaderURLs(cl: ClassLoader): Array[java.net.URL] = cl match {
case null => Array()
case u: java.net.URLClassLoader => u.getURLs ++ classLoaderURLs(cl.getParent)
case _ => classLoaderURLs(cl.getParent)
}

classLoaderURLs(Thread.currentThread().getContextClassLoader)
.foreach(u => command.settings.classpath.append(u.getPath))

// We have to make sure that scala macros are expandable. paradise plugin has to be added to
// -Xplugin paths. In case of assembly - paradise is included in assembly jar - thus we add
// itself to -Xplugin. If shell is started from sbt or classpath, paradise jar has to be in
// classpath, we find it and add it to -Xplugin.

// Repl assembly includes paradise's scalac-plugin.xml - required for BigQuery macro
// There should be no harm if we keep this for sbt launch.
val thisJar = this.getClass.getProtectionDomain.getCodeSource.getLocation.getPath
command.settings.plugin.appendToValue(thisJar)

ClassPath.split(command.settings.classpath.value)
.find(File(_).name.startsWith("paradise_"))
.foreach(command.settings.plugin.appendToValue)

// Useful settings for for debugging, dumping class files etc:
/* command.settings.debug.value = true
command.settings.Yreploutdir.tryToSet(List(""))
Expand All @@ -56,7 +80,9 @@ trait BaseScioShell extends MainGenericRunner {
// Force the repl to be synchronous, so all cmds are executed in the same thread
command.settings.Yreplsync.value = true

val scioClassLoader = new ScioReplClassLoader(command.settings.classpathURLs.toArray,
val scioClassLoader = new ScioReplClassLoader(
command.settings.classpathURLs.toArray ++
classLoaderURLs(Thread.currentThread().getContextClassLoader),
null,
Thread.currentThread.getContextClassLoader)

Expand All @@ -65,10 +91,12 @@ trait BaseScioShell extends MainGenericRunner {

// Set classloader chain - expose top level abstract class loader down
// the chain to allow for readObject and latestUserDefinedLoader
// See https://gist.github.com/harrah/404272
command.settings.embeddedDefaults(scioClassLoader)

repl.process(command.settings)
}
// scalastyle:on method.length

/** Runs an instance of the shell. */
def main(args: Array[String]) {
Expand Down