From 8e89d97e4775426666727ce7db5ed807d60ff7e3 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Tue, 1 Mar 2016 15:05:17 +0100 Subject: add signature to all generated files and remove files not regenerated in current run, fixes #16 --- .../spray/boilerplate/BoilerplatePlugin.scala | 51 +++++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/src/main/scala/spray/boilerplate/BoilerplatePlugin.scala b/src/main/scala/spray/boilerplate/BoilerplatePlugin.scala index 9394be8..ebd0d7d 100644 --- a/src/main/scala/spray/boilerplate/BoilerplatePlugin.scala +++ b/src/main/scala/spray/boilerplate/BoilerplatePlugin.scala @@ -6,34 +6,41 @@ */ package spray.boilerplate +import java.io.FileInputStream + import sbt._ import Keys._ +import sbt.plugins.JvmPlugin object BoilerplatePlugin extends AutoPlugin { override def trigger: PluginTrigger = noTrigger - override def `requires`: Plugins = empty + override def `requires`: Plugins = JvmPlugin object autoImport { val boilerplateGenerate = taskKey[Seq[File]]("Generates boilerplate from template files") val boilerplateSource = settingKey[File]("Default directory containing boilerplate template sources.") + val boilerplateSignature = settingKey[String]( + "Function that creates signature string to prepend to the generated file (given an input file name). " + + "Will be used to detect boilerplate-generated files") } import autoImport._ override def projectSettings: Seq[Def.Setting[_]] = - inConfig(Compile)(rawBoilerplateSettings) ++ inConfig(Test)(rawBoilerplateSettings) + inConfig(Compile)(rawBoilerplateSettings) ++ inConfig(Test)(rawBoilerplateSettings) ++ Seq( + boilerplateSignature := "// auto-generated by sbt-boilerplate\n") private def rawBoilerplateSettings: Seq[Setting[_]] = { val inputFilter = "*.template" Seq( boilerplateSource := sourceDirectory.value / "boilerplate", watchSources in Defaults.ConfigGlobal ++= ((boilerplateSource.value ** inputFilter) --- (boilerplateSource.value ** excludeFilter.value ** inputFilter)).get, - boilerplateGenerate := generateFromTemplates(streams.value, boilerplateSource.value, sourceManaged.value), + boilerplateGenerate := generateFromTemplates(streams.value, boilerplateSignature.value, boilerplateSource.value, sourceManaged.value), mappings in packageSrc ++= managedSources.value pair (Path.relativeTo(sourceManaged.value) | Path.flat), sourceGenerators <+= boilerplateGenerate) } - def generateFromTemplates(streams: TaskStreams, sourceDir: File, targetDir: File): Seq[File] = { + def generateFromTemplates(streams: TaskStreams, signature: String, sourceDir: File, targetDir: File): Seq[File] = { val files = sourceDir ** "*.template" def changeExtension(f: File): File = { @@ -49,16 +56,48 @@ object BoilerplatePlugin extends AutoPlugin { case (orig, target) ⇒ (orig, changeExtension(target)) } + val newFiles = mapping.map(_._2) + clearTargetDir(streams, targetDir, signature, newFiles) mapping foreach { case (templateFile, target) ⇒ if (templateFile.lastModified > target.lastModified) { streams.log.info("Generating '%s'" format target.getName) val template = IO.read(templateFile) - IO.write(target, Generator.generateFromTemplate(template, 22)) + IO.write(target, + signature + Generator.generateFromTemplate(template, 22)) } else streams.log.debug("Template '%s' older than target. Ignoring." format templateFile.getName) } - mapping.map(_._2) + newFiles + } + + def clearTargetDir(streams: TaskStreams, targetDir: File, signature: String, newFiles: Seq[File]): Seq[File] = { + val fileSet = newFiles.toSet + + val buffer = new Array[Byte](signature.getBytes("utf8").size) + def containsSignature(file: File): Boolean = { + val f = new FileInputStream(file) + try { + val read = f.read(buffer) + (read != buffer.length) || // if we haven't read the full signature assume we had read it + new String(buffer, "utf8") == signature + } finally f.close() + } + + val toRemove = + targetDir.*** + // apply filters with increasing effort + .filter(f ⇒ f.exists && f.isFile) + .filter(_.length >= signature.length) + .filter(!fileSet(_)) + .filter(containsSignature) + .get + + toRemove.foreach { f ⇒ + streams.log.debug(s"Removing $f that was formerly created by sbt-boilerplate (but won't be created anew).") + f.delete + } + toRemove } } -- cgit v1.2.3