Skip to content

Instantly share code, notes, and snippets.

@jrudolph
Last active August 29, 2015 14:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jrudolph/c79777cf374fbd3d2d1a to your computer and use it in GitHub Desktop.
Save jrudolph/c79777cf374fbd3d2d1a to your computer and use it in GitHub Desktop.
Setup per-branch target directories in sbt
// Helper snippet to enable per-git-branch target directories
//
// This will move the target directory for a sub-module away
// from <project-root>/<sub-module-name>/target
// to <project-root>/per-branch-targets/<branch-name>/<sub-module-name>
//
// Why?: shorter wait times if you switch branches often enough
// (Example: Akka's project file take 20+ seconds to compile and
// a single line change in AkkaBuild.scala will always
// trigger a complete rebuild.)
//
// Instructions:
// * put this file into every sub-project directory including `project`
// * don't forget to restart sbt after each branch change
//
// Caveat: you will need to rebuild your project once from scratch for every new branch
// (which can be seen as a feature)
//
// Bonus points:
// * if you can be adapt this to run on a btrfs which auto-initializes a new branch by
// copying data over from the "most related" branch
// * for adding some cleanup logic for pruning old/non-existant branch directories,
// for big projects this will quickly use lots of space (one akka-http Build ~= 100MB)
// * for making this an auto plugin, so you don't need to put it into every submodule manually
target := {
def gitBranchName(): String = "git rev-parse --abbrev-ref HEAD".!!.trim
def safeDirName(name: String): String = name.replaceAll("/", "_")
target.value.getParentFile.getParentFile / // TODO: replace by proper detection of the parent project root
"per-branch-targets" / safeDirName(gitBranchName()) / normalizedName.value
}
crossPaths := true
@aruediger
Copy link

Awesome! What's the motivation behind moving it up in the tree?

Alternative: target.value.getParentFile / target.value.getName + "-" + safeDirName(gitBranchName())

Stumbled upon the idea here the other day while thinking about sbt/sbt-boilerplate#16.

@jrudolph
Copy link
Author

I guess the reason was to keep everything belonging to one branch together. This simplifies maintenance somewhat.

@aruediger
Copy link

I see. Makes wiping the target dir easier.

One more thing: Is there a way to add this to akka's defaultSettings from an external *.sbt file?

I added

target := {
  try { target.value / "git rev-parse --abbrev-ref HEAD".!!.trim }
  catch { case t: Throwable => println(t); target.value }
}

to akka's defaultSettings and it works like a charm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment