How can I apply setting changes on onLoad hook in SBT?

左心房为你撑大大i 提交于 2020-03-02 04:39:26

问题


I have some settings in SBT that I need to generate values from after a loaded plugin has performed some side-effects. The onLoad hooks seem the best place to do that. The hook receives a State, transforms it and returns a new one. It's easy to schedule commands with State methods, but changing settings doesn't seem very easy.

I first tried the following code, which fails because it seems to cause a recursive call to onLoad and a failure due to a duplicate actor name (probably a product of the recursion).

onLoad in Global := (onLoad in Global).value andThen { state =>
  val settings = generateMySettings
  Project.extract(state).append(settings, state)
}

The other alternative I see is calling the put or update methods in State itself directly, but that seems quite ugly and error prone. Is there a better/cleaner way?


回答1:


There is a good example of how to "rewire" project settings in onLoad hook at github sbt repo: https://github.com/sbt/sbt-community-plugins/blob/master/project/Dependencies.scala

I'm not sure why the onLoad hook might be executed more than one time, but the solution to your problem is to simply define a boolean flag attribute to conditionally call your hook only once if the flag wasn't triggered yet.

In the mentioned example they're doing it exactly like this,

trait GenerateMySettingsStartup extends Build {
  private lazy val generated =  AttributeKey[Boolean]("my-settings-generated")
  def generateCommandName = "generate-my-settings"

  private final def fixState(state: State): State = 
    if(state.get(generated) getOrElse false) {
      state
    } else {
      // >>> generate and append your settings here <<<
      state.put(generated, true)
    }

  private def initialize = Command.command(generateCommandName)(fixState(_))

  final def generateSettings: Seq[Setting[_]] = Seq(
    commands += initialize,
    // initialize onLoad task if not yet defined
    onLoad in Global <<= (onLoad in Global) ?? idFun[State],
    // append generateCommandName onLoad handler
    onLoad in Global <<= (onLoad in Global) apply ( _ andThen (generateCommandName :: _))
  )
}

then just apply GenerateMySettingsStartup#generateSettings to your project's settings.

P.S. Not sure if I've got it all right, but here I think the onLoad hook was defined through Command because it has access to a State which might not be defined at certain scopes, just a wild guess so clarify me if my assumption is wrong, thanks!



来源:https://stackoverflow.com/questions/27760279/how-can-i-apply-setting-changes-on-onload-hook-in-sbt

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!