/sbt

http://github.com/scalaz/scalaz · #! · 543 lines · 467 code · 76 blank · 0 comment · 0 complexity · 7907dc867a3c1872c2ceaafe6b14c967 MD5 · raw file

  1. #!/usr/bin/env bash
  2. #
  3. # A more capable sbt runner, coincidentally also called sbt.
  4. # Author: Paul Phillips <paulp@improving.org>
  5. # todo - make this dynamic
  6. declare -r sbt_release_version="0.13.8"
  7. declare -r sbt_unreleased_version="0.13.9-M1"
  8. declare -r buildProps="project/build.properties"
  9. declare sbt_jar sbt_dir sbt_create sbt_version
  10. declare scala_version sbt_explicit_version
  11. declare verbose noshare batch trace_level log_level
  12. declare sbt_saved_stty debugUs
  13. echoerr () { echo >&2 "$@"; }
  14. vlog () { [[ -n "$verbose" ]] && echoerr "$@"; }
  15. # spaces are possible, e.g. sbt.version = 0.13.0
  16. build_props_sbt () {
  17. [[ -r "$buildProps" ]] && \
  18. grep '^sbt\.version' "$buildProps" | tr '=\r' ' ' | awk '{ print $2; }'
  19. }
  20. update_build_props_sbt () {
  21. local ver="$1"
  22. local old="$(build_props_sbt)"
  23. [[ -r "$buildProps" ]] && [[ "$ver" != "$old" ]] && {
  24. perl -pi -e "s/^sbt\.version\b.*\$/sbt.version=${ver}/" "$buildProps"
  25. grep -q '^sbt.version[ =]' "$buildProps" || printf "\nsbt.version=%s\n" "$ver" >> "$buildProps"
  26. vlog "!!!"
  27. vlog "!!! Updated file $buildProps setting sbt.version to: $ver"
  28. vlog "!!! Previous value was: $old"
  29. vlog "!!!"
  30. }
  31. }
  32. set_sbt_version () {
  33. sbt_version="${sbt_explicit_version:-$(build_props_sbt)}"
  34. [[ -n "$sbt_version" ]] || sbt_version=$sbt_release_version
  35. export sbt_version
  36. }
  37. # restore stty settings (echo in particular)
  38. onSbtRunnerExit() {
  39. [[ -n "$sbt_saved_stty" ]] || return
  40. vlog ""
  41. vlog "restoring stty: $sbt_saved_stty"
  42. stty "$sbt_saved_stty"
  43. unset sbt_saved_stty
  44. }
  45. # save stty and trap exit, to ensure echo is reenabled if we are interrupted.
  46. trap onSbtRunnerExit EXIT
  47. sbt_saved_stty="$(stty -g 2>/dev/null)"
  48. vlog "Saved stty: $sbt_saved_stty"
  49. # this seems to cover the bases on OSX, and someone will
  50. # have to tell me about the others.
  51. get_script_path () {
  52. local path="$1"
  53. [[ -L "$path" ]] || { echo "$path" ; return; }
  54. local target="$(readlink "$path")"
  55. if [[ "${target:0:1}" == "/" ]]; then
  56. echo "$target"
  57. else
  58. echo "${path%/*}/$target"
  59. fi
  60. }
  61. die() {
  62. echo "Aborting: $@"
  63. exit 1
  64. }
  65. make_url () {
  66. version="$1"
  67. case "$version" in
  68. 0.7.*) echo "http://simple-build-tool.googlecode.com/files/sbt-launch-0.7.7.jar" ;;
  69. 0.10.* ) echo "$sbt_launch_repo/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;;
  70. 0.11.[12]) echo "$sbt_launch_repo/org.scala-tools.sbt/sbt-launch/$version/sbt-launch.jar" ;;
  71. *) echo "$sbt_launch_repo/org.scala-sbt/sbt-launch/$version/sbt-launch.jar" ;;
  72. esac
  73. }
  74. init_default_option_file () {
  75. local overriding_var="${!1}"
  76. local default_file="$2"
  77. if [[ ! -r "$default_file" && "$overriding_var" =~ ^@(.*)$ ]]; then
  78. local envvar_file="${BASH_REMATCH[1]}"
  79. if [[ -r "$envvar_file" ]]; then
  80. default_file="$envvar_file"
  81. fi
  82. fi
  83. echo "$default_file"
  84. }
  85. declare -r cms_opts="-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC"
  86. declare -r jit_opts="-XX:ReservedCodeCacheSize=256m -XX:+TieredCompilation"
  87. declare -r default_jvm_opts_common="-Xms512m -Xmx1536m -Xss2m $jit_opts $cms_opts"
  88. declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy"
  89. declare -r latest_28="2.8.2"
  90. declare -r latest_29="2.9.3"
  91. declare -r latest_210="2.10.5"
  92. declare -r latest_211="2.11.7"
  93. declare -r script_path="$(get_script_path "$BASH_SOURCE")"
  94. declare -r script_name="${script_path##*/}"
  95. # some non-read-onlies set with defaults
  96. declare java_cmd="java"
  97. declare sbt_opts_file="$(init_default_option_file SBT_OPTS .sbtopts)"
  98. declare jvm_opts_file="$(init_default_option_file JVM_OPTS .jvmopts)"
  99. declare sbt_launch_repo="http://repo.typesafe.com/typesafe/ivy-releases"
  100. # pull -J and -D options to give to java.
  101. declare -a residual_args
  102. declare -a java_args
  103. declare -a scalac_args
  104. declare -a sbt_commands
  105. # args to jvm/sbt via files or environment variables
  106. declare -a extra_jvm_opts extra_sbt_opts
  107. addJava () {
  108. vlog "[addJava] arg = '$1'"
  109. java_args+=("$1")
  110. }
  111. addSbt () {
  112. vlog "[addSbt] arg = '$1'"
  113. sbt_commands+=("$1")
  114. }
  115. setThisBuild () {
  116. vlog "[addBuild] args = '$@'"
  117. local key="$1" && shift
  118. addSbt "set $key in ThisBuild := $@"
  119. }
  120. addScalac () {
  121. vlog "[addScalac] arg = '$1'"
  122. scalac_args+=("$1")
  123. }
  124. addResidual () {
  125. vlog "[residual] arg = '$1'"
  126. residual_args+=("$1")
  127. }
  128. addResolver () {
  129. addSbt "set resolvers += $1"
  130. }
  131. addDebugger () {
  132. addJava "-Xdebug"
  133. addJava "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1"
  134. }
  135. setScalaVersion () {
  136. [[ "$1" == *"-SNAPSHOT" ]] && addResolver 'Resolver.sonatypeRepo("snapshots")'
  137. addSbt "++ $1"
  138. }
  139. setJavaHome () {
  140. java_cmd="$1/bin/java"
  141. setThisBuild javaHome "Some(file(\"$1\"))"
  142. export JAVA_HOME="$1"
  143. export JDK_HOME="$1"
  144. export PATH="$JAVA_HOME/bin:$PATH"
  145. }
  146. setJavaHomeQuietly () {
  147. addSbt warn
  148. setJavaHome "$1"
  149. addSbt info
  150. }
  151. # if set, use JDK_HOME/JAVA_HOME over java found in path
  152. if [[ -e "$JDK_HOME/lib/tools.jar" ]]; then
  153. setJavaHomeQuietly "$JDK_HOME"
  154. elif [[ -e "$JAVA_HOME/bin/java" ]]; then
  155. setJavaHomeQuietly "$JAVA_HOME"
  156. fi
  157. # directory to store sbt launchers
  158. declare sbt_launch_dir="$HOME/.sbt/launchers"
  159. [[ -d "$sbt_launch_dir" ]] || mkdir -p "$sbt_launch_dir"
  160. [[ -w "$sbt_launch_dir" ]] || sbt_launch_dir="$(mktemp -d -t sbt_extras_launchers.XXXXXX)"
  161. java_version () {
  162. local version=$("$java_cmd" -version 2>&1 | grep -E -e '(java|openjdk) version' | awk '{ print $3 }' | tr -d \")
  163. vlog "Detected Java version: $version"
  164. echo "${version:2:1}"
  165. }
  166. # MaxPermSize critical on pre-8 jvms but incurs noisy warning on 8+
  167. default_jvm_opts () {
  168. local v="$(java_version)"
  169. if [[ $v -ge 8 ]]; then
  170. echo "$default_jvm_opts_common"
  171. else
  172. echo "-XX:MaxPermSize=384m $default_jvm_opts_common"
  173. fi
  174. }
  175. build_props_scala () {
  176. if [[ -r "$buildProps" ]]; then
  177. versionLine="$(grep '^build.scala.versions' "$buildProps")"
  178. versionString="${versionLine##build.scala.versions=}"
  179. echo "${versionString%% .*}"
  180. fi
  181. }
  182. execRunner () {
  183. # print the arguments one to a line, quoting any containing spaces
  184. vlog "# Executing command line:" && {
  185. for arg; do
  186. if [[ -n "$arg" ]]; then
  187. if printf "%s\n" "$arg" | grep -q ' '; then
  188. printf >&2 "\"%s\"\n" "$arg"
  189. else
  190. printf >&2 "%s\n" "$arg"
  191. fi
  192. fi
  193. done
  194. vlog ""
  195. }
  196. [[ -n "$batch" ]] && exec </dev/null
  197. exec "$@"
  198. }
  199. jar_url () {
  200. make_url "$1"
  201. }
  202. jar_file () {
  203. echo "$sbt_launch_dir/$1/sbt-launch.jar"
  204. }
  205. download_url () {
  206. local url="$1"
  207. local jar="$2"
  208. echoerr "Downloading sbt launcher for $sbt_version:"
  209. echoerr " From $url"
  210. echoerr " To $jar"
  211. mkdir -p "${jar%/*}" && {
  212. if which curl >/dev/null; then
  213. curl --fail --silent --location "$url" --output "$jar"
  214. elif which wget >/dev/null; then
  215. wget --quiet -O "$jar" "$url"
  216. fi
  217. } && [[ -r "$jar" ]]
  218. }
  219. acquire_sbt_jar () {
  220. sbt_url="$(jar_url "$sbt_version")"
  221. sbt_jar="$(jar_file "$sbt_version")"
  222. [[ -r "$sbt_jar" ]] || download_url "$sbt_url" "$sbt_jar"
  223. }
  224. usage () {
  225. cat <<EOM
  226. Usage: $script_name [options]
  227. Note that options which are passed along to sbt begin with -- whereas
  228. options to this runner use a single dash. Any sbt command can be scheduled
  229. to run first by prefixing the command with --, so --warn, --error and so on
  230. are not special.
  231. Output filtering: if there is a file in the home directory called .sbtignore
  232. and this is not an interactive sbt session, the file is treated as a list of
  233. bash regular expressions. Output lines which match any regex are not echoed.
  234. One can see exactly which lines would have been suppressed by starting this
  235. runner with the -x option.
  236. -h | -help print this message
  237. -v verbose operation (this runner is chattier)
  238. -d, -w, -q aliases for --debug, --warn, --error (q means quiet)
  239. -x debug this script
  240. -trace <level> display stack traces with a max of <level> frames (default: -1, traces suppressed)
  241. -debug-inc enable debugging log for the incremental compiler
  242. -no-colors disable ANSI color codes
  243. -sbt-create start sbt even if current directory contains no sbt project
  244. -sbt-dir <path> path to global settings/plugins directory (default: ~/.sbt/<version>)
  245. -sbt-boot <path> path to shared boot directory (default: ~/.sbt/boot in 0.11+)
  246. -ivy <path> path to local Ivy repository (default: ~/.ivy2)
  247. -no-share use all local caches; no sharing
  248. -offline put sbt in offline mode
  249. -jvm-debug <port> Turn on JVM debugging, open at the given port.
  250. -batch Disable interactive mode
  251. -prompt <expr> Set the sbt prompt; in expr, 's' is the State and 'e' is Extracted
  252. # sbt version (default: sbt.version from $buildProps if present, otherwise $sbt_release_version)
  253. -sbt-force-latest force the use of the latest release of sbt: $sbt_release_version
  254. -sbt-version <version> use the specified version of sbt (default: $sbt_release_version)
  255. -sbt-dev use the latest pre-release version of sbt: $sbt_unreleased_version
  256. -sbt-jar <path> use the specified jar as the sbt launcher
  257. -sbt-launch-dir <path> directory to hold sbt launchers (default: ~/.sbt/launchers)
  258. -sbt-launch-repo <url> repo url for downloading sbt launcher jar (default: $sbt_launch_repo)
  259. # scala version (default: as chosen by sbt)
  260. -28 use $latest_28
  261. -29 use $latest_29
  262. -210 use $latest_210
  263. -211 use $latest_211
  264. -scala-home <path> use the scala build at the specified directory
  265. -scala-version <version> use the specified version of scala
  266. -binary-version <version> use the specified scala version when searching for dependencies
  267. # java version (default: java from PATH, currently $(java -version 2>&1 | grep version))
  268. -java-home <path> alternate JAVA_HOME
  269. # passing options to the jvm - note it does NOT use JAVA_OPTS due to pollution
  270. # The default set is used if JVM_OPTS is unset and no -jvm-opts file is found
  271. <default> $(default_jvm_opts)
  272. JVM_OPTS environment variable holding either the jvm args directly, or
  273. the reference to a file containing jvm args if given path is prepended by '@' (e.g. '@/etc/jvmopts')
  274. Note: "@"-file is overridden by local '.jvmopts' or '-jvm-opts' argument.
  275. -jvm-opts <path> file containing jvm args (if not given, .jvmopts in project root is used if present)
  276. -Dkey=val pass -Dkey=val directly to the jvm
  277. -J-X pass option -X directly to the jvm (-J is stripped)
  278. # passing options to sbt, OR to this runner
  279. SBT_OPTS environment variable holding either the sbt args directly, or
  280. the reference to a file containing sbt args if given path is prepended by '@' (e.g. '@/etc/sbtopts')
  281. Note: "@"-file is overridden by local '.sbtopts' or '-sbt-opts' argument.
  282. -sbt-opts <path> file containing sbt args (if not given, .sbtopts in project root is used if present)
  283. -S-X add -X to sbt's scalacOptions (-S is stripped)
  284. EOM
  285. }
  286. process_args ()
  287. {
  288. require_arg () {
  289. local type="$1"
  290. local opt="$2"
  291. local arg="$3"
  292. if [[ -z "$arg" ]] || [[ "${arg:0:1}" == "-" ]]; then
  293. die "$opt requires <$type> argument"
  294. fi
  295. }
  296. while [[ $# -gt 0 ]]; do
  297. case "$1" in
  298. -h|-help) usage; exit 1 ;;
  299. -v) verbose=true && shift ;;
  300. -d) addSbt "--debug" && addSbt debug && shift ;;
  301. -w) addSbt "--warn" && addSbt warn && shift ;;
  302. -q) addSbt "--error" && addSbt error && shift ;;
  303. -x) debugUs=true && shift ;;
  304. -trace) require_arg integer "$1" "$2" && trace_level="$2" && shift 2 ;;
  305. -ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;;
  306. -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;;
  307. -no-share) noshare=true && shift ;;
  308. -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;;
  309. -sbt-dir) require_arg path "$1" "$2" && sbt_dir="$2" && shift 2 ;;
  310. -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;;
  311. -offline) addSbt "set offline := true" && shift ;;
  312. -jvm-debug) require_arg port "$1" "$2" && addDebugger "$2" && shift 2 ;;
  313. -batch) batch=true && shift ;;
  314. -prompt) require_arg "expr" "$1" "$2" && setThisBuild shellPrompt "(s => { val e = Project.extract(s) ; $2 })" && shift 2 ;;
  315. -sbt-create) sbt_create=true && shift ;;
  316. -sbt-jar) require_arg path "$1" "$2" && sbt_jar="$2" && shift 2 ;;
  317. -sbt-version) require_arg version "$1" "$2" && sbt_explicit_version="$2" && shift 2 ;;
  318. -sbt-force-latest) sbt_explicit_version="$sbt_release_version" && shift ;;
  319. -sbt-dev) sbt_explicit_version="$sbt_unreleased_version" && shift ;;
  320. -sbt-launch-dir) require_arg path "$1" "$2" && sbt_launch_dir="$2" && shift 2 ;;
  321. -sbt-launch-repo) require_arg path "$1" "$2" && sbt_launch_repo="$2" && shift 2 ;;
  322. -scala-version) require_arg version "$1" "$2" && setScalaVersion "$2" && shift 2 ;;
  323. -binary-version) require_arg version "$1" "$2" && setThisBuild scalaBinaryVersion "\"$2\"" && shift 2 ;;
  324. -scala-home) require_arg path "$1" "$2" && setThisBuild scalaHome "Some(file(\"$2\"))" && shift 2 ;;
  325. -java-home) require_arg path "$1" "$2" && setJavaHome "$2" && shift 2 ;;
  326. -sbt-opts) require_arg path "$1" "$2" && sbt_opts_file="$2" && shift 2 ;;
  327. -jvm-opts) require_arg path "$1" "$2" && jvm_opts_file="$2" && shift 2 ;;
  328. -D*) addJava "$1" && shift ;;
  329. -J*) addJava "${1:2}" && shift ;;
  330. -S*) addScalac "${1:2}" && shift ;;
  331. -28) setScalaVersion "$latest_28" && shift ;;
  332. -29) setScalaVersion "$latest_29" && shift ;;
  333. -210) setScalaVersion "$latest_210" && shift ;;
  334. -211) setScalaVersion "$latest_211" && shift ;;
  335. --debug) addSbt debug && addResidual "$1" && shift ;;
  336. --warn) addSbt warn && addResidual "$1" && shift ;;
  337. --error) addSbt error && addResidual "$1" && shift ;;
  338. *) addResidual "$1" && shift ;;
  339. esac
  340. done
  341. }
  342. # process the direct command line arguments
  343. process_args "$@"
  344. # skip #-styled comments and blank lines
  345. readConfigFile() {
  346. while read line; do
  347. [[ $line =~ ^# ]] || [[ -z $line ]] || echo "$line"
  348. done < "$1"
  349. }
  350. # if there are file/environment sbt_opts, process again so we
  351. # can supply args to this runner
  352. if [[ -r "$sbt_opts_file" ]]; then
  353. vlog "Using sbt options defined in file $sbt_opts_file"
  354. while read opt; do extra_sbt_opts+=("$opt"); done < <(readConfigFile "$sbt_opts_file")
  355. elif [[ -n "$SBT_OPTS" && ! ("$SBT_OPTS" =~ ^@.*) ]]; then
  356. vlog "Using sbt options defined in variable \$SBT_OPTS"
  357. extra_sbt_opts=( $SBT_OPTS )
  358. else
  359. vlog "No extra sbt options have been defined"
  360. fi
  361. [[ -n "${extra_sbt_opts[*]}" ]] && process_args "${extra_sbt_opts[@]}"
  362. # reset "$@" to the residual args
  363. set -- "${residual_args[@]}"
  364. argumentCount=$#
  365. # set sbt version
  366. set_sbt_version
  367. # only exists in 0.12+
  368. setTraceLevel() {
  369. case "$sbt_version" in
  370. "0.7."* | "0.10."* | "0.11."* ) echoerr "Cannot set trace level in sbt version $sbt_version" ;;
  371. *) setThisBuild traceLevel $trace_level ;;
  372. esac
  373. }
  374. # set scalacOptions if we were given any -S opts
  375. [[ ${#scalac_args[@]} -eq 0 ]] || addSbt "set scalacOptions in ThisBuild += \"${scalac_args[@]}\""
  376. # Update build.properties on disk to set explicit version - sbt gives us no choice
  377. [[ -n "$sbt_explicit_version" ]] && update_build_props_sbt "$sbt_explicit_version"
  378. vlog "Detected sbt version $sbt_version"
  379. [[ -n "$scala_version" ]] && vlog "Overriding scala version to $scala_version"
  380. # no args - alert them there's stuff in here
  381. (( argumentCount > 0 )) || {
  382. vlog "Starting $script_name: invoke with -help for other options"
  383. residual_args=( shell )
  384. }
  385. # verify this is an sbt dir or -create was given
  386. [[ -r ./build.sbt || -d ./project || -n "$sbt_create" ]] || {
  387. cat <<EOM
  388. $(pwd) doesn't appear to be an sbt project.
  389. If you want to start sbt anyway, run:
  390. $0 -sbt-create
  391. EOM
  392. exit 1
  393. }
  394. # pick up completion if present; todo
  395. [[ -r .sbt_completion.sh ]] && source .sbt_completion.sh
  396. # no jar? download it.
  397. [[ -r "$sbt_jar" ]] || acquire_sbt_jar || {
  398. # still no jar? uh-oh.
  399. echo "Download failed. Obtain the jar manually and place it at $sbt_jar"
  400. exit 1
  401. }
  402. if [[ -n "$noshare" ]]; then
  403. for opt in ${noshare_opts}; do
  404. addJava "$opt"
  405. done
  406. else
  407. case "$sbt_version" in
  408. "0.7."* | "0.10."* | "0.11."* | "0.12."* )
  409. [[ -n "$sbt_dir" ]] || {
  410. sbt_dir="$HOME/.sbt/$sbt_version"
  411. vlog "Using $sbt_dir as sbt dir, -sbt-dir to override."
  412. }
  413. ;;
  414. esac
  415. if [[ -n "$sbt_dir" ]]; then
  416. addJava "-Dsbt.global.base=$sbt_dir"
  417. fi
  418. fi
  419. if [[ -r "$jvm_opts_file" ]]; then
  420. vlog "Using jvm options defined in file $jvm_opts_file"
  421. while read opt; do extra_jvm_opts+=("$opt"); done < <(readConfigFile "$jvm_opts_file")
  422. elif [[ -n "$JVM_OPTS" && ! ("$JVM_OPTS" =~ ^@.*) ]]; then
  423. vlog "Using jvm options defined in \$JVM_OPTS variable"
  424. extra_jvm_opts=( $JVM_OPTS )
  425. else
  426. vlog "Using default jvm options"
  427. extra_jvm_opts=( $(default_jvm_opts) )
  428. fi
  429. # traceLevel is 0.12+
  430. [[ -n "$trace_level" ]] && setTraceLevel
  431. main () {
  432. execRunner "$java_cmd" \
  433. "${extra_jvm_opts[@]}" \
  434. "${java_args[@]}" \
  435. -jar "$sbt_jar" \
  436. "${sbt_commands[@]}" \
  437. "${residual_args[@]}"
  438. }
  439. # sbt inserts this string on certain lines when formatting is enabled:
  440. # val OverwriteLine = "\r\u001BM\u001B[2K"
  441. # ...in order not to spam the console with a million "Resolving" lines.
  442. # Unfortunately that makes it that much harder to work with when
  443. # we're not going to print those lines anyway. We strip that bit of
  444. # line noise, but leave the other codes to preserve color.
  445. mainFiltered () {
  446. local ansiOverwrite='\r\x1BM\x1B[2K'
  447. local excludeRegex=$(egrep -v '^#|^$' ~/.sbtignore | paste -sd'|' -)
  448. echoLine () {
  449. local line="$1"
  450. local line1="$(echo "$line" | sed -r 's/\r\x1BM\x1B\[2K//g')" # This strips the OverwriteLine code.
  451. local line2="$(echo "$line1" | sed -r 's/\x1B\[[0-9;]*[JKmsu]//g')" # This strips all codes - we test regexes against this.
  452. if [[ $line2 =~ $excludeRegex ]]; then
  453. [[ -n $debugUs ]] && echo "[X] $line1"
  454. else
  455. [[ -n $debugUs ]] && echo " $line1" || echo "$line1"
  456. fi
  457. }
  458. echoLine "Starting sbt with output filtering enabled."
  459. main | while read -r line; do echoLine "$line"; done
  460. }
  461. # Only filter if there's a filter file and we don't see a known interactive command.
  462. # Obviously this is super ad hoc but I don't know how to improve on it. Testing whether
  463. # stdin is a terminal is useless because most of my use cases for this filtering are
  464. # exactly when I'm at a terminal, running sbt non-interactively.
  465. shouldFilter () { [[ -f ~/.sbtignore ]] && ! egrep -q '\b(shell|console|consoleProject)\b' <<<"${residual_args[@]}"; }
  466. # run sbt
  467. if shouldFilter; then mainFiltered; else main; fi