risor icon indicating copy to clipboard operation
risor copied to clipboard

some exec/arguments issues

Open rprtr258 opened this issue 1 year ago • 1 comments

  • first, exec.command has signature with variadic arguments:
command(name string, args ...string) command

but user functions cannot have variadic arguments, nor there is spread operator. So, I cannot write function like:

func myexec(cmd, args) {
  c := exec.command(cmd, args) // type error: expected a string (list given)
  exit_code := try(c.run, 1)
  if exit_code != 0 {
    print("COMMAND FAILED:", cmd, args)
    print("STDOUT:", c.stdout)
    print("STDERR:", c.stderr)
  }
}
  • second, it would be nice to print stacktrace when error has occured, because raw error message says nearly nothing
  • third, it seems shebang shenninghans for cli package doesn't work for me.
    • first issue is that shebang passes arguments like so:
    $SHEBANG $SCRIPT $ARGS
    
    so, when shebang is #!/usr/bin/env risor -- it gives
    /usr/bin/env: ‘risor --’: No such file or directory
    /usr/bin/env: use -[v]S to pass options in shebang lines
    
    If we fix shebang to #!/usr/bin/env -S risor --, following program is being executed:
    /usr/bin/env -S risor -- script.risor $ARGS
    
    which in turn calls
    risor -- script.risor $ARGS
    
    BUT, as I understood, risor for some reason requires script to be in form risor script.risor -- $ARGS so actual behavior now is open risor repl. Though, for now this can be sidestepped with following shebang:
    #!/usr/bin/awk BEGIN{for (i=2; i<ARGC; i++) { subslice = subslice ARGV[i] " " }; system("risor "ARGV[1]" -- "subslice)}
    
    • second issue is that when we finally were able to call risor correctly, os.args gives array of strings from $ARGS we passed along. BUT it should also include the script, such that os.args() == ["./script.rasor", $ARGS...]. Because of that, I cannot pass os.args() to cli.app.run() because the latter requires executable to be the first argument, which again can be sidestepped for now with .run(["vahui"] + os.args())
  • one more issue is with running exec: there is no way to catch exit code. The only way to not fail script and handle failed command for now goes like
c := exec.command(cmd, args)
exit_code := try(c.run, 1) // 1 is returned instead of actual non-zero code
if exit_code != 0 {
  print("COMMAND FAILED:", cmd, args)
  print("STDOUT:", c.stdout)
  print("STDERR:", c.stderr)
}

such wrapper can be useful for e.g. printing failed command, printing it's stderr to get reason of failure, instead of just

exit status 1

which is not informative at all.

rprtr258 avatar Apr 24 '24 00:04 rprtr258

Thanks @rprtr258

I'll review all this, but I think a couple of these issues I have started to fix already. Others not yet.

Regarding the CLI and shebang lines, this branch has relevant improvements: https://github.com/risor-io/risor/compare/cli-fix?expand=1

The splat operator issue I came across as well and have started to implement here: https://github.com/risor-io/risor/compare/variadic-calls?expand=1

I think that branch needs a bit more work.

I agree the exec module has a couple deficiencies. I'll review your comments in more detail.

myzie avatar Apr 24 '24 00:04 myzie