<commit_before>package sbtappengine

import sbt._
import sbt.Process._

object AppenginePlugin {
  import Keys._
  import Project.Initialize
  import com.github.siasia.WebPlugin._

  val Appengine = config("appengine")

  val requestLogs   = InputKey[Unit]("request-logs", "Write request logs in Apache common log format.")
  val rollback      = InputKey[Unit]("rollback", "Rollback an in-progress update.")
  val deploy        = InputKey[Unit]("deploy", "Create or update an app version.")
  val deployIndexes = InputKey[Unit]("deploy-indexes", "Update application indexes.")
  val deployCron    = InputKey[Unit]("deploy-cron", "Update application cron jobs.")
  val deployQueues  = InputKey[Unit]("deploy-queues", "Update application task queue definitions.")
  val deployDos     = InputKey[Unit]("deploy-dos", "Update application DoS protection configuration.")
  val cronInfo      = InputKey[Unit]("cron-info", "Displays times for the next several runs of each cron job.")

  val sdkVersion    = SettingKey[String]("sdk-version")
  val appengineSdkPath = SettingKey[File]("appengine-sdk-path")
  val appengineClasspath = SettingKey[Classpath]("appengine-classpath")
  val appengineApiJarName = SettingKey[String]("appengine-api-jar-name")
  val appengineApiLabsJarName = SettingKey[String]("appengine-api-labs-jar-name")
  val appengineJSR107CacheJarName = SettingKey[String]("appengine-jsr107-cache-jar-name")
  val jsr107CacheJarName = SettingKey[String]("jsr107-cache-jar-name")
  val appengineBinPath = SettingKey[File]("appengine-bin-path")
  val appengineLibPath = SettingKey[File]("appengine-lib-path")
  val appengineLibUserPath = SettingKey[File]("appengine-lib-user-path")
  val appengineLibImplPath = SettingKey[File]("appengine-lib-impl-path")
  val appengineApiJarPath = SettingKey[File]("appengine-api-jar-path")
  val appcfgName    = SettingKey[String]("appcfg-name")
  val appcfgPath    = SettingKey[File]("appcfg-path")
  val emptyMap      = TaskKey[Seq[(File, String)]]("empty-map")

  private def appcfgTask(action: String, outputFile: Option[String],
                         args: TaskKey[Seq[String]], depends: TaskKey[Seq[(File, String)]] = emptyMap) =
    (args, temporaryWarPath, appcfgPath, streams, depends) map { (args, w, appcfgPath, s, m) =>
      val terminal = (Some(jline.Terminal.getTerminal)
        filter {_.isInstanceOf[jline.UnixTerminal]}
        map {_.asInstanceOf[jline.UnixTerminal] })
      val command: ProcessBuilder = <x>
        {appcfgPath.absolutePath} {args.mkString(" ")} {action} {w.absolutePath} {outputFile.mkString}
      </x>
      s.log.debug("Executing command " + command)
      terminal.foreach(_.restoreTerminal)
      try {
        val exitValue = command.run(true).exitValue() // don't buffer output
        if(exitValue == 0) None
        else Some("Nonzero exit value: " + exitValue)
        ()
      } finally {
        terminal.foreach(_.initializeTerminal)
      }
    }

  private def buildAppengineSdkPath: File = {
    val sdk = System.getenv("APPENGINE_SDK_HOME")
    if (sdk == null) error("You need to set APPENGINE_SDK_HOME")
    new File(sdk)
  }

  private def buildSdkVersion(libUserPath: File): String = {
    val pat = """appengine-api-1.0-sdk-(\d\.\d\.\d(?:\.\d)*)\.jar""".r
    (libUserPath * "appengine-api-1.0-sdk-*.jar").get.toList match {
      case jar::_ => jar.name match {
        case pat(version) => version
        case _ => error("invalid jar file. " + jar)
      }
      case _ => error("not found appengine api jar.")
    }
  }

  def isWindows = System.getProperty("os.name").startsWith("Windows")
  def osBatchSuffix = if (isWindows) ".cmd" else ".sh"

  lazy val settings = webSettings ++ inConfig(Appengine)(Seq(
    prepareWebapp    <<= (prepareWebapp in Compile).identity,
    temporaryWarPath <<= (temporaryWarPath in Compile).identity,
    webappResources  <<= (webappResources in Compile).identity,
    webappUnmanaged  <<= (temporaryWarPath) { (dir) => dir / "WEB-INF" / "appengine-generated" *** },
    unmanagedClasspath  <++= (appengineClasspath) map { (cp) => cp },

    requestLogs <<= inputTask { (args: TaskKey[Seq[String]])   => appcfgTask("request_logs", Some("request.log"), args) },
    rollback <<= inputTask { (args: TaskKey[Seq[String]])      => appcfgTask("rollback", None, args) },
    deploy <<= inputTask { (args: TaskKey[Seq[String]])        => appcfgTask("update", None, args, prepareWebapp) },
    deployIndexes <<= inputTask { (args: TaskKey[Seq[String]]) => appcfgTask("update_indexes", None, args, prepareWebapp) },
    deployCron <<= inputTask { (args: TaskKey[Seq[String]])    => appcfgTask("update_cron", None, args, prepareWebapp) },
    deployQueues <<= inputTask { (args: TaskKey[Seq[String]])  => appcfgTask("update_queues", None, args, prepareWebapp) },
    deployDos <<= inputTask { (args: TaskKey[Seq[String]])     => appcfgTask("update_dos", None, args, prepareWebapp) },
    cronInfo <<= inputTask { (args: TaskKey[Seq[String]])      => appcfgTask("cron_info", None, args) },

    sdkVersion <<= (appengineLibUserPath) { (dir) => buildSdkVersion(dir) },
    appengineSdkPath := buildAppengineSdkPath,
    appengineClasspath <<= (appengineApiJarPath) { (jar: File) => Attributed.blankSeq(Seq(jar)) },
    appengineApiJarName <<= (sdkVersion) { (v) => "appengine-api-1.0-sdk-" + v + ".jar" },
    appengineApiLabsJarName <<= (sdkVersion) { (v) => "appengine-api-labs-" + v + ".jar" },
    appengineJSR107CacheJarName <<= (sdkVersion) { (v) => "appengine-jsr107cache-" + v + ".jar" },
    jsr107CacheJarName := "jsr107cache-1.1.jar",

    appengineBinPath <<= (appengineSdkPath) { (dir) => dir / "bin" },
    appengineLibPath <<= (appengineSdkPath) { (dir) => dir / "lib" },
    appengineLibUserPath <<= (appengineLibPath) { (dir) => dir / "user" },
    appengineLibImplPath <<= (appengineLibPath) { (dir) => dir / "impl" },
    appengineApiJarPath <<= (appengineLibUserPath, appengineApiJarName) { (dir, name) => dir / name },
    appcfgName := "appcfg" + osBatchSuffix,
    appcfgPath <<= (appengineBinPath, appcfgName) { (dir, name) => dir / name },
    emptyMap := Nil
  )) ++
  inConfig(Test)(Seq(
    unmanagedClasspath <++= (appengineClasspath) map { (cp) => cp },
    appengineClasspath <<= (appengineClasspath in Appengine,
      appengineLibImplPath in Appengine, appengineLibPath in Appengine) { (cp, impl, lib) =>
      val impljars = (impl * "*.jar").get
      val testingjars = (lib / "testing" * "*.jar").get
      cp ++ Attributed.blankSeq(impljars ++ testingjars)
    }
  ))

  /*
  def appengineToolsJarPath = (appengineLibPath / "appengine-tools-api.jar")
  */
  /* Overrides jar present as of sdk 1.4.3 */
  /*
  def appengineOverridePath = appengineSdkPath / "lib" / "override"
  def overridesJarName = "appengine-dev-jdk-overrides.jar"<commit_msg>fixed unmangedClasspath<commit_after>package sbtappengine

import sbt._
import sbt.Process._

object AppenginePlugin {
  import Keys._
  import Project.Initialize
  import com.github.siasia.WebPlugin
  import WebPlugin._

  val Appengine = config("appengine")

  val requestLogs   = InputKey[Unit]("request-logs", "Write request logs in Apache common log format.")
  val rollback      = InputKey[Unit]("rollback", "Rollback an in-progress update.")
  val deploy        = InputKey[Unit]("deploy", "Create or update an app version.")
  val deployIndexes = InputKey[Unit]("deploy-indexes", "Update application indexes.")
  val deployCron    = InputKey[Unit]("deploy-cron", "Update application cron jobs.")
  val deployQueues  = InputKey[Unit]("deploy-queues", "Update application task queue definitions.")
  val deployDos     = InputKey[Unit]("deploy-dos", "Update application DoS protection configuration.")
  val cronInfo      = InputKey[Unit]("cron-info", "Displays times for the next several runs of each cron job.")

  val sdkVersion    = SettingKey[String]("sdk-version")
  val appengineSdkPath = SettingKey[File]("appengine-sdk-path")
  val appengineClasspath = SettingKey[Classpath]("appengine-classpath")
  val appengineApiJarName = SettingKey[String]("appengine-api-jar-name")
  val appengineApiLabsJarName = SettingKey[String]("appengine-api-labs-jar-name")
  val appengineJSR107CacheJarName = SettingKey[String]("appengine-jsr107-cache-jar-name")
  val jsr107CacheJarName = SettingKey[String]("jsr107-cache-jar-name")
  val appengineBinPath = SettingKey[File]("appengine-bin-path")
  val appengineLibPath = SettingKey[File]("appengine-lib-path")
  val appengineLibUserPath = SettingKey[File]("appengine-lib-user-path")
  val appengineLibImplPath = SettingKey[File]("appengine-lib-impl-path")
  val appengineApiJarPath = SettingKey[File]("appengine-api-jar-path")
  val appcfgName    = SettingKey[String]("appcfg-name")
  val appcfgPath    = SettingKey[File]("appcfg-path")
  val emptyMap      = TaskKey[Seq[(File, String)]]("empty-map")

  private def appcfgTask(action: String, outputFile: Option[String],
                         args: TaskKey[Seq[String]], depends: TaskKey[Seq[(File, String)]] = emptyMap) =
    (args, temporaryWarPath, appcfgPath, streams, depends) map { (args, w, appcfgPath, s, m) =>
      val terminal = (Some(jline.Terminal.getTerminal)
        filter {_.isInstanceOf[jline.UnixTerminal]}
        map {_.asInstanceOf[jline.UnixTerminal] })
      val command: ProcessBuilder = <x>
        {appcfgPath.absolutePath} {args.mkString(" ")} {action} {w.absolutePath} {outputFile.mkString}
      </x>
      s.log.debug("Executing command " + command)
      terminal.foreach(_.restoreTerminal)
      try {
        val exitValue = command.run(true).exitValue() // don't buffer output
        if(exitValue == 0) None
        else Some("Nonzero exit value: " + exitValue)
        ()
      } finally {
        terminal.foreach(_.initializeTerminal)
      }
    }

  private def buildAppengineSdkPath: File = {
    val sdk = System.getenv("APPENGINE_SDK_HOME")
    if (sdk == null) error("You need to set APPENGINE_SDK_HOME")
    new File(sdk)
  }

  private def buildSdkVersion(libUserPath: File): String = {
    val pat = """appengine-api-1.0-sdk-(\d\.\d\.\d(?:\.\d)*)\.jar""".r
    (libUserPath * "appengine-api-1.0-sdk-*.jar").get.toList match {
      case jar::_ => jar.name match {
        case pat(version) => version
        case _ => error("invalid jar file. " + jar)
      }
      case _ => error("not found appengine api jar.")
    }
  }

  def isWindows = System.getProperty("os.name").startsWith("Windows")
  def osBatchSuffix = if (isWindows) ".cmd" else ".sh"

  val webSettings: Seq[Project.Setting[_]] = WebPlugin.webSettings ++ inConfig(Appengine)(Seq(
    prepareWebapp    <<= (prepareWebapp in Compile).identity,
    temporaryWarPath <<= (temporaryWarPath in Compile).identity,
    webappResources  <<= (webappResources in Compile).identity,
    webappUnmanaged  <<= (temporaryWarPath) { (dir) => dir / "WEB-INF" / "appengine-generated" *** },
    unmanagedClasspath  <<= (unmanagedClasspath in Compile, appengineClasspath) map { (orig, cp) => orig ++ cp },

    requestLogs <<= inputTask { (args: TaskKey[Seq[String]])   => appcfgTask("request_logs", Some("request.log"), args) },
    rollback <<= inputTask { (args: TaskKey[Seq[String]])      => appcfgTask("rollback", None, args) },
    deploy <<= inputTask { (args: TaskKey[Seq[String]])        => appcfgTask("update", None, args, prepareWebapp) },
    deployIndexes <<= inputTask { (args: TaskKey[Seq[String]]) => appcfgTask("update_indexes", None, args, prepareWebapp) },
    deployCron <<= inputTask { (args: TaskKey[Seq[String]])    => appcfgTask("update_cron", None, args, prepareWebapp) },
    deployQueues <<= inputTask { (args: TaskKey[Seq[String]])  => appcfgTask("update_queues", None, args, prepareWebapp) },
    deployDos <<= inputTask { (args: TaskKey[Seq[String]])     => appcfgTask("update_dos", None, args, prepareWebapp) },
    cronInfo <<= inputTask { (args: TaskKey[Seq[String]])      => appcfgTask("cron_info", None, args) },

    sdkVersion <<= (appengineLibUserPath) { (dir) => buildSdkVersion(dir) },
    appengineSdkPath := buildAppengineSdkPath,
    appengineClasspath <<= (appengineApiJarPath) { (jar: File) => Attributed.blankSeq(Seq(jar)) },
    appengineApiJarName <<= (sdkVersion) { (v) => "appengine-api-1.0-sdk-" + v + ".jar" },
    appengineApiLabsJarName <<= (sdkVersion) { (v) => "appengine-api-labs-" + v + ".jar" },
    appengineJSR107CacheJarName <<= (sdkVersion) { (v) => "appengine-jsr107cache-" + v + ".jar" },
    jsr107CacheJarName := "jsr107cache-1.1.jar",

    appengineBinPath <<= (appengineSdkPath) { (dir) => dir / "bin" },
    appengineLibPath <<= (appengineSdkPath) { (dir) => dir / "lib" },
    appengineLibUserPath <<= (appengineLibPath) { (dir) => dir / "user" },
    appengineLibImplPath <<= (appengineLibPath) { (dir) => dir / "impl" },
    appengineApiJarPath <<= (appengineLibUserPath, appengineApiJarName) { (dir, name) => dir / name },
    appcfgName := "appcfg" + osBatchSuffix,
    appcfgPath <<= (appengineBinPath, appcfgName) { (dir, name) => dir / name },
    emptyMap := Nil
  )) ++
  inConfig(Test)(Seq(
    unmanagedClasspath <++= (appengineClasspath) map { (cp) => cp },
    appengineClasspath <<= (appengineClasspath in Appengine,
      appengineLibImplPath in Appengine, appengineLibPath in Appengine) { (cp, impl, lib) =>
      val impljars = (impl * "*.jar").get
      val testingjars = (lib / "testing" * "*.jar").get
      cp ++ Attributed.blankSeq(impljars ++ testingjars)
    }
  )) ++
  Seq(
    unmanagedClasspath in Compile  <++= (appengineClasspath in Appengine) map { (cp) => cp }
  )

  /*
  def appengineToolsJarPath = (appengineLibPath / "appengine-tools-api.jar")
  */
  /* Overrides jar present as of sdk 1.4.3 */
  /*
  def appengineOverridePath = appengineSdkPath / "lib" / "override"
  def overridesJarName = "appengine-dev-jdk-overrides.jar"
{'fraction_non_alphanumeric': 0.15432410952965825, 'fraction_numerical': 0.0052019362762806155, 'mean_word_length': 4.006148282097649, 'pattern_counts': {'":': 0, '<': 109, '<?xml version=': 0, '>': 64, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2348223', 'n_tokens_mistral': 4630, 'n_tokens_neox': 4541, 'n_words': 935}