sbt 21 KB

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