From 74c6ec9d0a357191ef4a4ed15be7fc23116799c0 Mon Sep 17 00:00:00 2001 From: Jon Pretty Date: Wed, 5 Jun 2024 12:06:04 +0200 Subject: [PATCH] Updates for Scala 3.5 --- src/core/guillotine.scala | 41 +++++++++++++------------ src/core/posix.scala | 5 ++- src/test/tests.scala | 64 +++++++++++++++++++-------------------- 3 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/core/guillotine.scala b/src/core/guillotine.scala index b445b03..922eb92 100644 --- a/src/core/guillotine.scala +++ b/src/core/guillotine.scala @@ -75,8 +75,8 @@ trait Executor[ResultType]: trait ProcessRef: def pid: Pid - def kill()(using GenericLogger): Unit - def abort()(using GenericLogger): Unit + def kill(): Unit binds GenericLogger + def abort(): Unit binds GenericLogger def alive: Boolean def attend(): Unit def startTime[InstantType: SpecificInstant]: Optional[InstantType] @@ -95,8 +95,8 @@ object OsProcess: class OsProcess private (java: ProcessHandle) extends ProcessRef: def pid: Pid = Pid(java.pid) - def kill()(using GenericLogger): Unit = java.destroy() - def abort()(using GenericLogger): Unit = java.destroyForcibly() + def kill(): Unit binds GenericLogger = java.destroy() + def abort(): Unit binds GenericLogger = java.destroyForcibly() def alive: Boolean = java.isAlive def attend(): Unit = java.onExit.nn.get() @@ -147,12 +147,12 @@ class Process[+ExecType <: Label, ResultType](process: java.lang.Process) extend case 0 => ExitStatus.Ok case other => ExitStatus.Fail(other) - def abort()(using logger: GenericLogger): Unit = - logger.info(t"The process with PID ${pid.value} was aborted") + def abort(): Unit binds GenericLogger = + bond[GenericLogger].info(t"The process with PID ${pid.value} was aborted") process.destroy() - def kill()(using logger: GenericLogger): Unit = - logger.warn(t"The process with PID ${pid.value} was killed") + def kill(): Unit binds GenericLogger = + bond[GenericLogger].warn(t"The process with PID ${pid.value} was killed") process.destroyForcibly() def osProcess(using Errant[PidError]) = OsProcess(pid) @@ -172,18 +172,18 @@ class Process[+ExecType <: Label, ResultType](process: java.lang.Process) extend sealed trait Executable: type Exec <: Label - def fork[ResultType]()(using working: WorkingDirectory, logger: GenericLogger) - : Process[Exec, ResultType] raises ExecError + def fork[ResultType]()(using working: WorkingDirectory) + : Process[Exec, ResultType] binds GenericLogger raises ExecError def exec[ResultType]() - (using working: WorkingDirectory, logger: GenericLogger, executor: Executor[ResultType]) - : ResultType raises ExecError = + (using working: WorkingDirectory, executor: Executor[ResultType]) + : ResultType binds GenericLogger raises ExecError = fork[ResultType]().await() def apply[ResultType]()(using erased commandOutput: CommandOutput[Exec, ResultType]) - (using working: WorkingDirectory, logger: GenericLogger, executor: Executor[ResultType]) - : ResultType raises ExecError = + (using working: WorkingDirectory, executor: Executor[ResultType]) + : ResultType binds GenericLogger raises ExecError = fork[ResultType]().await() @@ -221,8 +221,8 @@ object Command: given Show[Command] = command => formattedArguments(command.arguments) case class Command(arguments: Text*) extends Executable: - def fork[ResultType]()(using working: WorkingDirectory, logger: GenericLogger) - : Process[Exec, ResultType] raises ExecError = + def fork[ResultType]()(using working: WorkingDirectory) + : Process[Exec, ResultType] binds GenericLogger raises ExecError = val processBuilder = ProcessBuilder(arguments.ss*) processBuilder.directory(ji.File(working.directory().s)) @@ -240,8 +240,8 @@ object Pipeline: given Show[Pipeline] = _.commands.map(_.show).join(t" | ") case class Pipeline(commands: Command*) extends Executable: - def fork[ResultType]()(using working: WorkingDirectory, logger: GenericLogger) - : Process[Exec, ResultType] raises ExecError = + def fork[ResultType]()(using working: WorkingDirectory) + : Process[Exec, ResultType] binds GenericLogger raises ExecError = val processBuilders = commands.map: command => val processBuilder = ProcessBuilder(command.arguments.ss*) @@ -250,7 +250,7 @@ case class Pipeline(commands: Command*) extends Executable: processBuilder.nn - logger.info(t"Starting pipelined processes ${this}") + bond[GenericLogger].info(t"Starting pipelined processes ${this}") val pipeline = ProcessBuilder.startPipeline(processBuilders.asJava).nn.asScala.to(List).last new Process[Exec, ResultType](pipeline) @@ -374,7 +374,6 @@ trait Parameterizable: def show(value: Self): Text object Guillotine: - given Realm = realm"guillotine" def sh(context: Expr[StringContext], parts: Expr[Seq[Any]])(using Quotes): Expr[Command] = import quotes.reflect.* @@ -385,3 +384,5 @@ object Guillotine: (Refinement(TypeRepr.of[Command], "Exec", bounds).asType: @unchecked) match case '[type commandType <: Command; commandType] => '{${Sh.Prefix.expand(context, parts)}.asInstanceOf[commandType]} + +given Realm = realm"guillotine" diff --git a/src/core/posix.scala b/src/core/posix.scala index 53d7a89..8ca1c1e 100644 --- a/src/core/posix.scala +++ b/src/core/posix.scala @@ -117,6 +117,9 @@ trait PosixCommandOutputs: erased given uuencode: CommandOutput["uuencode", Text] = ### erased given waitCommand: CommandOutput["wait", Text] = ### erased given wc: CommandOutput["wc", Text] = ### - erased given which[PathType](using erased SpecificPath { type Self = PathType }): CommandOutput["which", PathType] = ### + + erased given which[PathType](using erased PathType is SpecificPath) + : CommandOutput["which", PathType] = ### + erased given who: CommandOutput["who", Text] = ### erased given write: CommandOutput["write", Text] = ### diff --git a/src/test/tests.scala b/src/test/tests.scala index abdfa2e..29949dc 100644 --- a/src/test/tests.scala +++ b/src/test/tests.scala @@ -31,7 +31,7 @@ import contingency.*, errorHandlers.throwUnsafely import unsafeExceptions.canThrowAny -given Log[Text] = logging.silent +given SimpleLogger = logging.silent object Tests extends Suite(t"Guillotine tests"): def run(): Unit = @@ -39,102 +39,102 @@ object Tests extends Suite(t"Guillotine tests"): test(t"parse simple command"): sh"ls -la" .assert(_ == Command(t"ls", t"-la")) - + test(t"parse a substitution"): val flags = t"-la" val file = t"filename" sh"ls $flags" .assert(_ == Command(t"ls", t"-la")) - + test(t"parse two substitutions"): val flags = t"-la" val file = t"filename" sh"ls $flags $file" .assert(_ == Command(t"ls", t"-la", t"filename")) - + test(t"parse irregular spacing"): val flags = t"-la" val file = t"filename" sh"ls $flags $file" .assert(_ == Command(t"ls", t"-la", t"filename")) - + test(t"parse irregular spacing 2"): val flags = t"-la" val file = t"filename" sh"ls $flags $file" .assert(_ == Command(t"ls", t"-la", t"filename")) - + test(t"adjacent substitutions"): val a = t"a" val b = t"b" sh"ls $a$b" .assert(_ == Command(t"ls", t"ab")) - + test(t"substitute a list"): val a = List(t"a", t"b") sh"ls $a" .assert(_ == Command(t"ls", t"a", t"b")) - + test(t"substitute a single-quoted list"): val a = List(t"a", t"b") sh"ls '$a'" .assert(_ == Command(t"ls", t"a b")) - + test(t"substitute in a double-quoted list"): val a = List(t"a", t"b") sh"""ls "$a"""" .assert(_ == Command(t"ls", t"a b")) - + test(t"insertion after arg"): val a = List(t"a", t"b") sh"""ls ${a}x""" .assert(_ == Command(t"ls", t"a", t"bx")) - + test(t"insertion before arg"): val a = List(t"a", t"b") sh"""ls x${a}""" .assert(_ == Command(t"ls", t"xa", t"b")) - + test(t"insertion before quoted arg"): val a = List(t"a", t"b") sh"""ls ${a}'x'""" .assert(_ == Command(t"ls", t"a", t"bx")) - + test(t"insertion after quoted arg"): val a = List(t"a", t"b") sh"""ls 'x'${a}""" .assert(_ == Command(t"ls", t"xa", t"b")) - + test(t"empty list insertion"): val a = List() sh"""ls ${a}""" .assert(_ == Command(t"ls")) - + test(t"empty list insertion"): val a = List() sh"""ls '${a}'""" .assert(_ == Command(t"ls", t"")) - + test(t"empty parameters"): sh"""ls '' ''""" .assert(_ == Command(t"ls", t"", t"")) - + test(t"one empty parameter, specified twice"): sh"""ls ''''""" .assert(_ == Command(t"ls", t"")) - + test(t"single quote inside double quotes"): sh"""ls "'" """ .assert(_ == Command(t"ls", t"'")) - + test(t"double quote inside single quotes"): sh"""ls '"' """ .assert(_ == Command(t"ls", t"\"")) - + test(t"escaped double quote"): sh"""ls \" """ .assert(_ == Command(t"ls", t"\"")) - + test(t"escaped single quote"): sh"""ls \' """ .assert(_ == Command(t"ls", t"'")) @@ -143,11 +143,12 @@ object Tests extends Suite(t"Guillotine tests"): test(t"simple command"): sh"echo Hello World".debug .check(_ == t"""sh"echo Hello World"""") - + + println(sh"echo 'Hello World'".debug) test(t"simple command with space"): sh"echo 'Hello World'".debug .check(_ == t"""sh"echo 'Hello World'"""") - + test(t"simple command with quote and space"): Command(t"echo", t"Don't stop").debug .check(_ == t"sh\"\"\"echo \"Don't stop\"\"\"\"") @@ -164,7 +165,7 @@ object Tests extends Suite(t"Guillotine tests"): test(t"check that two commands written differently are equivalent"): sh"echo 'hello world'" .assert(_ == sh"""echo "hello world"""") - + test(t"check that two commands written with different whitespace are equivalent"): sh"one two three" .assert(_ == sh"one two three") @@ -199,27 +200,27 @@ object Tests extends Suite(t"Guillotine tests"): sh"sleep 0.2".fork[Unit]() System.currentTimeMillis - t0 .assert(_ <= 100L) - + test(t"exec sleeping process"): val t0 = System.currentTimeMillis sh"sleep 0.2".exec[Unit]() System.currentTimeMillis - t0 .assert(_ >= 200L) - + test(t"fork and await sleeping process"): val t0 = System.currentTimeMillis val proc = sh"sleep 0.2".fork[Unit]() proc.await() System.currentTimeMillis - t0 .assert(_ >= 200L) - + test(t"fork and abort sleeping process"): val t0 = System.currentTimeMillis val proc = sh"sleep 0.2".fork[Unit]() proc.abort() System.currentTimeMillis - t0 .assert(_ <= 100L) - + test(t"fork and kill sleeping process"): val t0 = System.currentTimeMillis val proc = sh"sleep 0.2".fork[Unit]() @@ -230,7 +231,7 @@ object Tests extends Suite(t"Guillotine tests"): test(t"successful exit status"): sh"echo hello".exec[ExitStatus]() .assert(_ == ExitStatus.Ok) - + test(t"failed exit status"): sh"false".exec[ExitStatus]() .assert(_ == ExitStatus.Fail(1)) @@ -243,9 +244,8 @@ object Tests extends Suite(t"Guillotine tests"): test(t"implied return type"): sh"echo 'Hello world'"() .assert(_ == t"Hello world") - + test(t"implied return type for `which`"): - import filesystemInterfaces.galileiApi + import filesystemApi.galileiPath sh"which cat"() .assert(_ == Unix / p"bin" / p"cat") -