SBT how to run InputTask - scala

I am creating some custom tasks in my SBT project and need to call other tasks for that.
How can i call inputTasks from inside my tasks and support them some input?

Since you can factor your own tasks around this I'm assuming you're trying to use the run task. It took a bit of digging, but I've finally made it work; in a nutshell, this is what you do (assuming your task is named deployTask, tweak to match your needs):
deployTask <<= ( fullClasspath in Compile, runner ) map { ( classpath, runner ) =>
val logger = ConsoleLogger() // Not sure this is optimal
Run.executeTrapExit( {
Run.run( "com.sample.MainClass",
classpath map { _.data },
Seq( "option1", "option2", "..." ), // <-- Options go here
logger )( runner )
}, logger )
}
This doesn't invoke the InputTask directly (I haven't found a way to do that yet), but it at least lets you run arbitrary Java code.

Related

How to call an InputKey from within a Task in an SBT Plugin

I am trying to make a task execute several inputKey.
myTask := Def.taskDyn {
val outputOfMyInputKey = myInputKey.[WHAT SHOULD I DO HERE].value
Def.task {
// do something with outputOfMyInputKey
}
}
Anybody knows how to call inputKey with default parameters ?
I tried parsed , evaluated, value, inputTaskValue but none of them works.
Thanks.
Take a look at this section of the sbt docs: Get a Task from an InputTask. You can use .toTask to provide input for your input task:
myInputKey.toTask("").value
Notice that if you provide a non-empty input, it should start with a space:
myInputKey.toTask(" arg1 arg2").value

How do I get args passed to this scala object?

I'm trying to figure out how to pass args to this scala object:
I have this class written in this sbt project path: allaboutscala/src/main/scala/gzip_practice/gzipwriter
package gzip_practice
import java.io._
import java.util.zip._
/** Gzcat
*/
object gzcat extends App {
private val buf = new Array[Byte](1024)
try {
for (path <- args) {
try {
var in = new GZIPInputStream(new FileInputStream(path))
var n = in.read(buf)
while (n >= 0) {
System.out.write(buf, 0, n)
n = in.read(buf)
}
}
catch {
case _:FileNotFoundException =>
System.err.printf("File Not Found: %s", path)
case _:SecurityException =>
System.err.printf("Permission Denied: %s", path)
}
}
}
finally {
System.out.flush
}
}
This is an sbt project called allaboutscala. I am trying to run it with:
scala src/main/scala/gzip_practice/gzipwriter.scala "hi" but the command just hangs and I don't know why.
How am I supposed to run this object constructor with args?
You can use the scala command as a script runner.
Normally, it will wrap your "script" code in a main method.
But if you have an object with a main method, like your App, it will use that for the entry point.
However, it doesn't like package statements in the script.
If you comment out your package statement, you can compile and run with:
scala -nc somefile.scala myarg.gz
-nc means "no compile daemon"; otherwise, it will start a second process to compile scripts, so that subsequent compiles go faster; but it is a brittle workflow and I don't recommend it.
I confirmed that your code works.
Usually, folks use sbt or an IDE to compile and package in a jar to run with scala myapp.jar.
An object is a static instance of a class. You could construct it using:
object gzcat(args: String*) extends App {
...
}
args is bound as a val within the object gzcat.
Are you trying to run it with repl? I would suggest running it with sbt, then you can run sbt projects from project root directory with command line parameter as follows:
sbt "run file1.txt file2.txt"
The quotes are required. If you leave sbt shell open, then it running it will be much faster. Open shell in project root with
sbt
In the sbt shell:
run file1.txt file2.txt
Within the sbt shell, no quotes.

SBT Command that Calls Another Command and an InputTask

I am writing an SBT Command that is supposed to call another command (eclipse from the Eclipse SBT Plugin) and another InputTask.
How can one achieve this?
Assuming that you want to create a "release" command and it needs to call another task named "pack", you can add the following code to build.sbt:
commands += Command.command("release")((state:State) => {
Project.evaluateTask(pack, state)
println("release called")
state
})
Updated:
In addition, if you have to create the "release" command and it requires calling another command named "init_compile", then the following sample code can be used:
commands += Command.command("init_compile")((state:State) => {
println("init_compile called.")
state
})
commands += Command.command("release")((state:State) => {
val newState = Command.process("init_compile",state)
println("release called.")
newState
})

sbt package separate jars for different test types

We have just upgraded to using sbt 12.2 on our project. I would like to have our tests packaged in separate jars such as: project-unit.jar, project-integration.jar
Our current folder structure is:
src
main
...
test
scala
com.company.unit
com.company.integration
com.company.functional
Any suggestion is very much appreciated.
Thanks
I have found a way to do this by:
Create a packaging task for the appropriate test type:
val integrationPackaging = TaskKey[File]("package-integration")
Add package settings to the test settings:
lazy val integrationTestSettings = createTestSettings("integration", IntegrationTests) ++ createPackageSettings("integration", IntegrationTests, integrationPackaging)
private def createPackageSettings(testType: String, testConfiguration: Configuration, packagingTaskKey: TaskKey[sbt.File]) = {
inConfig(testConfiguration)(Defaults.testSettings) ++
Defaults.packageTaskSettings(packagingTaskKey, mappings in (Test, packageBin)) ++
(artifactName in packagingTaskKey := {(scalaversion, moduleId, artifact) => "%s_%s-%s-%s.jar" format (moduleId.name, scalaversion.binary, buildVersion, testType)}) ++
(mappings in packagingTaskKey ~= { (ms: Seq[(File,String)]) =>
ms.filter { case (file, path) =>{ !file.getName.endsWith(".class") || file.getAbsolutePath.contains(testType) }
}
})
}
Note in the create package settings, I had to:
add default test settings to ensure all test settings are inherited
add default test package task settings (using mappings in Test packageBin)
add artifactName (what you want the jar name to be)
add specific mappings for the package task key (created in step 1 above), this is the crux of it, I had to define a filter that ensures only files with the path containing the testType (e.g. "integration", "unit" or "functional") are selected and resource files (e.g. files that do not end with ".class")

SBT 0.11 InputKey depending on other tasks

In 0.7.x we used dependsOn to declare that a task depends on other tasks - meaning other tasks have to be executed first.
In 0.11.x we use <<= to declare that a task depends on some other task. The SBT wiki says a lot on how to declare a TaskKey[_] which depends on other tasks and settings (there are questions here that deal with that), but not much on InputKey[_]. If I have an input key declared like this:
val benchTask = InputKey[Unit](
"bench",
"Runs a specified benchmark."
) <<= inputTask {
(argTask: TaskKey[Seq[String]]) =>
argTask map {
args =>
// ...
} // xxx
}
How can I make it depend on other tasks, like for example packageBin in Test? I can put dependsOn instead of the xxx comment above, but that gives me type errors.
Thank you.
Map your other task together with argTask:
inputTask {
(argTask: TaskKey[Seq[String]]) =>
(argTask, packageBin in Test) map {
(args, pb) =>
// ...
}
}