Skip to content

Commit 59eaeaf

Browse files
authored
Merge pull request #11489 from philwalk/mingw-msys-repl-scripting
Fixes for various problems related to scripting.
2 parents d8a788e + f1598a7 commit 59eaeaf

File tree

8 files changed

+132
-35
lines changed

8 files changed

+132
-35
lines changed

compiler/src/dotty/tools/repl/JLineTerminal.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ final class JLineTerminal extends java.io.Closeable {
2020

2121
private val terminal =
2222
TerminalBuilder.builder()
23-
.dumb(false) // fail early if not able to create a terminal
23+
.dumb(dumbTerminal) // fail early if not able to create a terminal
2424
.build()
2525
private val history = new DefaultHistory
26+
def dumbTerminal = Option(System.getenv("TERM")) == Some("dumb")
2627

2728
private def blue(str: String)(using Context) =
2829
if (ctx.settings.color.value != "never") Console.BLUE + str + Console.RESET

compiler/src/dotty/tools/scripting/Main.scala

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package dotty.tools.scripting
22

33
import java.io.File
4-
import java.nio.file.Path
4+
import java.nio.file.{Path, Paths}
55
import dotty.tools.dotc.config.Properties.isWin
66

77
/** Main entry point to the Scripting execution engine */
@@ -60,7 +60,7 @@ object Main:
6060
def scriptBasename = scriptFile.getName.takeWhile(_!='.')
6161
val jarPath = s"$jarTargetDir/$scriptBasename.jar"
6262

63-
val cpPaths = runtimeClasspath.split(pathsep).map(_.absPath)
63+
val cpPaths = runtimeClasspath.split(pathsep).map(_.toUrl)
6464

6565
import java.util.jar.Attributes.Name
6666
val cpString:String = cpPaths.distinct.mkString(" ")
@@ -80,29 +80,26 @@ object Main:
8080

8181
def pathsep = sys.props("path.separator")
8282

83-
84-
extension(file: File){
85-
def norm: String = file.toString.norm
86-
}
87-
8883
extension(path: String) {
8984
// Normalize path separator, convert relative path to absolute
9085
def norm: String =
9186
path.replace('\\', '/') match {
92-
case s if s.secondChar == ":" => s.drop(2)
87+
case s if s.secondChar == ":" => s
9388
case s if s.startsWith("./") => s.drop(2)
9489
case s => s
9590
}
9691

9792
// convert to absolute path relative to cwd.
9893
def absPath: String = norm match
9994
case str if str.isAbsolute => norm
100-
case _ => s"/${sys.props("user.dir").norm}/$norm"
95+
case _ => Paths.get(userDir,norm).toString.norm
10196

102-
def absFile: File = File(path.absPath)
97+
def toUrl: String = Paths.get(absPath).toUri.toURL.toString
10398

10499
// Treat norm paths with a leading '/' as absolute.
105100
// Windows java.io.File#isAbsolute treats them as relative.
106101
def isAbsolute = path.norm.startsWith("/") || (isWin && path.secondChar == ":")
107102
def secondChar: String = path.take(2).drop(1).mkString("")
108103
}
104+
105+
lazy val userDir = sys.props("user.dir").norm
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env scala
2+
# comment
3+
STUFF=nada
4+
!#
5+
6+
def main(args: Array[String]): Unit =
7+
System.err.printf("mainClassFromStack: %s\n",mainFromStack)
8+
assert(mainFromStack.contains("hashBang"),s"fromStack[$mainFromStack]")
9+
10+
lazy val mainFromStack:String = {
11+
val result = new java.io.StringWriter()
12+
new RuntimeException("stack").printStackTrace(new java.io.PrintWriter(result))
13+
val stack = result.toString.split("[\r\n]+").toList
14+
//for( s <- stack ){ System.err.printf("[%s]\n",s) }
15+
stack.filter { str => str.contains(".main(") }.map {
16+
_.replaceAll(".*[(]","").
17+
replaceAll("\\.main\\(.*","").
18+
replaceAll(".scala.*","")
19+
}.distinct.take(1).mkString("")
20+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env scala
2+
export STUFF=nada
3+
#lots of other stuff that isn't valid scala
4+
!#
5+
object Zoo {
6+
def main(args: Array[String]): Unit =
7+
printf("script.name: %s\n",sys.props("script.name"))
8+
printf("mainClassFromStack: %s\n",mainFromStack)
9+
assert(mainFromStack == "Zoo",s"fromStack[$mainFromStack]")
10+
11+
lazy val mainFromStack:String = {
12+
val result = new java.io.StringWriter()
13+
new RuntimeException("stack").printStackTrace(new java.io.PrintWriter(result))
14+
val stack = result.toString.split("[\r\n]+").toList
15+
// for( s <- stack ){ System.err.printf("[%s]\n",s) }
16+
val shortStack = stack.filter { str => str.contains(".main(") && ! str.contains("$") }.map {
17+
_.replaceAll("[.].*","").replaceAll("\\s+at\\s+","")
18+
}
19+
// for( s <- shortStack ){ System.err.printf("[%s]\n",s) }
20+
shortStack.take(1).mkString("|")
21+
}
22+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env scala
2+
3+
def main(args: Array[String]): Unit =
4+
val name = Option(sys.props("script.name")) match {
5+
case None => printf("no script.name property is defined\n")
6+
case Some(name) =>
7+
printf("script.name: %s\n",name)
8+
assert(name == "scriptName.scala")
9+
}

dist/bin/common

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,39 @@
44
# * Credits: This script is based on the script generated by sbt-pack.
55
# *--------------------------------------------------------------------------*/
66

7+
# save terminal settings
8+
saved_stty=$(stty -g 2>/dev/null)
9+
# clear on error so we don't later try to restore them
10+
if [[ ! $? ]]; then
11+
saved_stty=""
12+
fi
13+
14+
# restore stty settings (echo in particular)
15+
function restoreSttySettings() {
16+
stty $saved_stty
17+
saved_stty=""
18+
}
19+
20+
scala_exit_status=127
21+
function onExit() {
22+
[[ "$saved_stty" != "" ]] && restoreSttySettings
23+
exit $scala_exit_status
24+
}
25+
26+
# to reenable echo if we are interrupted before completing.
27+
trap onExit INT TERM
28+
729
cygwin=false
830
mingw=false
31+
msys=false
932
darwin=false
1033
case "`uname`" in
1134
CYGWIN*) cygwin=true
1235
;;
1336
MINGW*) mingw=true
1437
;;
38+
MSYS*) msys=true
39+
;;
1540
Darwin*) darwin=true
1641
if [ -z "$JAVA_VERSION" ] ; then
1742
JAVA_VERSION="CurrentJDK"
@@ -25,6 +50,18 @@ case "`uname`" in
2550
;;
2651
esac
2752

53+
unset CYGPATHCMD
54+
if [[ ($cygwin||$mingw||$msys) ]]; then
55+
# cygpath is used by various windows shells: cygwin, git-sdk, gitbash, msys, etc.
56+
CYGPATHCMD=`which cygpath 2>/dev/null`
57+
case "$TERM" in
58+
rxvt* | xterm* | cygwin*)
59+
stty -icanon min 1 -echo
60+
SCALA_OPTS="$SCALA_OPTS -Djline.terminal=unix"
61+
;;
62+
esac
63+
fi
64+
2865
# Resolve JAVA_HOME from javac command path
2966
if [ -z "$JAVA_HOME" ]; then
3067
javaExecutable="`which javac`"
@@ -41,9 +78,8 @@ if [ -z "$JAVA_HOME" ]; then
4178
fi
4279
fi
4380

44-
45-
if [ -z "$JAVACMD" ] ; then
46-
if [ -n "$JAVA_HOME" ] ; then
81+
if [ -z "${JAVACMD-}" ] ; then
82+
if [ -n "${JAVA_HOME-}" ] ; then
4783
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
4884
# IBM's JDK on AIX uses strange locations for the executables
4985
JAVACMD="$JAVA_HOME/jre/sh/java"
@@ -69,18 +105,16 @@ CLASSPATH_SUFFIX=""
69105
# Path separator used in EXTRA_CLASSPATH
70106
PSEP=":"
71107

72-
# For Cygwin, switch paths to Windows-mixed format before running java
73-
if $cygwin; then
108+
# translate paths to Windows-mixed format before running java
109+
if [ -n "$CYGPATHCMD" ]; then
74110
[ -n "$PROG_HOME" ] &&
75-
PROG_HOME=`cygpath -am "$PROG_HOME"`
111+
PROG_HOME=`"$CYGPATHCMD" -am "$PROG_HOME"`
76112
[ -n "$JAVA_HOME" ] &&
77-
JAVA_HOME=`cygpath -am "$JAVA_HOME"`
113+
JAVA_HOME=`"$CYGPATHCMD" -am "$JAVA_HOME"`
78114
CLASSPATH_SUFFIX=";"
79115
PSEP=";"
80-
fi
81-
82-
# For Migwn, ensure paths are in UNIX format before anything is touched
83-
if $mingw ; then
116+
elif ($mingw || $msys); then
117+
# For Mingw / Msys, convert paths from UNIX format before anything is touched
84118
[ -n "$PROG_HOME" ] &&
85119
PROG_HOME="`(cd "$PROG_HOME"; pwd -W | sed 's|/|\\\\|g')`"
86120
[ -n "$JAVA_HOME" ] &&
@@ -95,9 +129,9 @@ fi
95129

96130
find_lib () {
97131
local lib=$(find $PROG_HOME/lib/ -name "$1")
98-
if $cygwin; then
99-
cygpath -am $lib
100-
elif $mingw; then
132+
if [ -n "$CYGPATHCMD" ]; then
133+
$CYGPATHCMD -am $lib
134+
elif ($mingw || $msys); then
101135
echo $lib | sed 's|/|\\\\|g'
102136
else
103137
echo $lib
@@ -116,7 +150,7 @@ SBT_INTF=$(find_lib "*compiler-interface*")
116150
JLINE_READER=$(find_lib "*jline-reader-3*")
117151
JLINE_TERMINAL=$(find_lib "*jline-terminal-3*")
118152
JLINE_TERMINAL_JNA=$(find_lib "*jline-terminal-jna-3*")
119-
JNA=$(find_lib "*jna-5*")
153+
[[ ($mingw||$msys) ]] || JNA=$(find_lib "*jna-5*")
120154

121155
# debug
122156
DEBUG_STR=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005

dist/bin/scala

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ while [[ $# -gt 0 ]]; do
9292
DEBUG="$DEBUG_STR"
9393
shift
9494
;;
95+
-version)
96+
# defer to scalac, then exit
97+
addScalacOptions "${1}"
98+
shift
99+
eval "\"$PROG_HOME/bin/scalac\" ${cp_arg-} ${java_options[@]}"
100+
scala_exit_status=$?
101+
onExit
102+
;;
95103
-J*)
96104
addJvmOptions "${1:2}"
97105
addScalacOptions "${1}"
@@ -115,26 +123,29 @@ while [[ $# -gt 0 ]]; do
115123
done
116124

117125
if [ $execute_script == true ]; then
118-
[ -n "$script_trace" ] && set -x
126+
[ -n "${script_trace-}" ] && set -x
119127
if [ "$CLASS_PATH" ]; then
120128
cp_arg="-classpath \"$CLASS_PATH\""
121129
fi
122130
java_options+=(${scala_script_options})
123131
setScriptName="-Dscript.path=$target_script"
124132
target_jar="${target_script%.*}.jar"
125133
if [[ $save_compiled == true && "$target_jar" -nt "$target_script" ]]; then
126-
eval exec "\"$JAVACMD\"" $setScriptName -jar "$target_jar" "${script_args[@]}"
134+
eval "\"$JAVACMD\"" $setScriptName -jar "$target_jar" "${script_args[@]}"
135+
scala_exit_status=$?
127136
else
128137
[[ $save_compiled == true ]] && rm -f $target_jar
129138
residual_args+=($setScriptName)
130-
eval "\"$PROG_HOME/bin/scalac\" $cp_arg ${java_options[@]} ${residual_args[@]} -script $target_script ${script_args[@]}"
139+
eval "\"$PROG_HOME/bin/scalac\" ${cp_arg-} ${java_options[@]} ${residual_args[@]} -script $target_script ${script_args[@]}"
140+
scala_exit_status=$?
131141
fi
132142
elif [ $execute_repl == true ] || ([ $execute_run == false ] && [ $options_indicator == 0 ]); then
133143
if [ "$CLASS_PATH" ]; then
134144
cp_arg="-classpath \"$CLASS_PATH\""
135145
fi
136146
echo "Starting scala3 REPL..."
137-
eval "\"$PROG_HOME/bin/scalac\" $cp_arg ${java_options[@]} -repl ${residual_args[@]}"
147+
eval "\"$PROG_HOME/bin/scalac\" ${cp_arg-} ${java_options[@]} -repl ${residual_args[@]}"
148+
scala_exit_status=$?
138149
elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then
139150
cp_arg="$DOTTY_LIB$PSEP$SCALA_LIB"
140151
if [ -z "$CLASS_PATH" ]; then
@@ -148,7 +159,10 @@ elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then
148159
if [ $with_compiler == true ]; then
149160
cp_arg+="$PSEP$DOTTY_COMP$PSEP$TASTY_CORE$PSEP$DOTTY_INTF$PSEP$SCALA_ASM$PSEP$DOTTY_STAGING$PSEP$DOTTY_TASTY_INSPECTOR"
150161
fi
151-
eval exec "\"$JAVACMD\"" "$DEBUG" "-classpath \"$cp_arg\"" "${jvm_options[@]}" "${residual_args[@]}"
162+
# exec here would prevent onExit from being called, leaving terminal in unusable state
163+
eval "\"$JAVACMD\"" "$DEBUG" "-classpath \"$cp_arg\"" "${jvm_options[@]}" "${residual_args[@]}"
164+
scala_exit_status=$?
152165
else
153-
echo "warning: command option is not correct."
166+
echo "warning: command option is not correct."
154167
fi
168+
onExit

dist/bin/scalac

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ classpathArgs () {
7474
toolchain+="$JLINE_READER$PSEP"
7575
toolchain+="$JLINE_TERMINAL$PSEP"
7676
toolchain+="$JLINE_TERMINAL_JNA$PSEP"
77-
toolchain+="$JNA"
77+
toolchain+="$JNA$PSEP"
7878

7979
jvm_cp_args="-classpath \"$toolchain\""
8080
}
@@ -123,12 +123,12 @@ fi
123123

124124
eval exec "\"$JAVACMD\"" \
125125
${JAVA_OPTS:-$default_java_opts} \
126-
"$DEBUG" \
126+
"${DEBUG-}" \
127127
"${java_args[@]}" \
128128
"$jvm_cp_args" \
129129
-Dscala.usejavacp=true \
130130
"$PROG_NAME" \
131131
"${scala_args[@]}" \
132132
"${residual_args[@]}" \
133-
"$scripting_string"
133+
"${scripting_string-}"
134134
exit $?

0 commit comments

Comments
 (0)