Getting Settings and Arguments with SBTs InputTask

I've written an SBT plugin that allows SBT users to define arbitrary tasks in their project that can be run (with full classpath and dependencies loaded) from SBT itself.

The body of the functionality looks like this

  def installTask(taskName: String, taskDescription: String = "") = {
    TaskKey[Unit](taskName, taskDescription) <<= (dependencyClasspath in Runtime)
      .map(loadTask(_, "tasks", taskName.capitalize))
      .map(_.run)
  }


  private def loadTask(dependencies: Keys.Classpath, taskPackage:String, className: String) = {
    val dependenciesUrls = dependencies.map(_.data.toURI.toURL).toArray
    val classLoader = new URLClassLoader(dependenciesUrls, null)
    val taskClass = s"$taskPackage.$className"
    classLoader.loadClass(taskClass).newInstance().asInstanceOf[Runnable]
  }

So people can, in their SBT file do this

import SbtTasks._

installTask("seedDB")

And when the call sbt seedDB the tasks.SeedDB will be executed in the application context.

Now the problem - I need to do this but accept arguments. I've got as far as understanding how to accept arguments

  def installTaskWithArgs(taskName: String, taskDescription: String = "") = {
    val input = InputKey[Unit](taskName, taskDescription)

    input := {
      val args: Seq[String] = Def.spaceDelimited("<arg>").parsed
      println(args)
    }
  }

But I can't work out how to, in this context access the values of my dependencyClasspath within the InputTask

  val dc = (dependencyClasspath in Runtime)

I also tried Commands but they seemed a bit more troublesome and all content appears to promote InputTasks over Commands anyway.

So - how do I accept arguments in a task while also getting access to the dependencyClasspath?

NB: Code has been elided for brevity please excuse any obvious exclusions

Answers


So after a few more days of experimenting I finally found a workable solution,

def installTaskWithArgs(taskName: String, taskDescription: String = "") = {
    val input = InputKey[Unit](taskName, taskDescription)

    input := {
      val args: Seq[String] = Def.spaceDelimited("<arg>").parsed
      val dc = (dependencyClasspath in Runtime).result.value.toEither.right.get
      println(args)
      println(dc)
    }
 }

I want to specifically call out the line

val dc = (dependencyClasspath in Runtime).result.value.toEither.right.get

While this isn't the most stable line (it assumes the happy path) this is at least a good starting point (and for my needs currently works)


I think inputTaskDyn is your friend here:

input :=
  Def.inputTaskDyn {
    val args = Def.spaceDelimited("<arg>").parsed
    val dc = (dependencyClasspath in Runtime).value
    ...
  }.evaluated

for some background and links to further reading, see https://github.com/sbt/sbt/issues/999


Need Your Help

Get a variable out of a try

java methods try-catch

I have a problem using a variable surrounded with a try :

Python Custom Logger

python logging tornado-motor

I have actually got the steps to follow to create the custom logger from the below link:

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.