mvdan / sh

A shell parser, formatter, and interpreter with bash support; includes shfmt
https://pkg.go.dev/mvdan.cc/sh/v3
BSD 3-Clause "New" or "Revised" License
6.97k stars 332 forks source link

Runner.Subshell() returns Runner with empty Env and Vars #1007

Open mattimo opened 1 year ago

mattimo commented 1 year ago

Consider the following code

r, _ := interp.New()
fmt.Printf("%#v\n", r.Env)
sub := r.Subshell()
fmt.Printf("%#v\n", sub.Env)

This prints

expand.listEnviron{"TERM=xterm-kitty", "TERMINFO=/usr/lib64/kitty/terminfo", "USER=matti", "USERNAME=matti" ...}
<nil>

The documentation for Subshell() states the following:

The copy will have the same environment, including variables and functions, but they can all be modified without affecting the original.

So I would have expected the runner from the subshell to include a copy of Env.

The same behavior is shown for Vars too. The interesting thing is that even when Running something in the runner r the behavior doesn't change.

mvdan commented 1 year ago

Just so I understand, what are you trying to accomplish by looking at the Env field? It's a read-only environment, so the contents shouldn't be particularly interesting as they won't change over time. I agree that the current behavior of the API is slightly confusing, and we should probably fix that, but I think you likely want a different kind of API.

mattimo commented 1 year ago

I'm trying to "source" a shell script and use the exports from there to create an env that I can pass to exec.Cmd.

I thought it would be easiest to just loop through Runner.Vars or Runner.Env to create the slice that I can then put into exec.Cmd. I'd of couse have to copy all the "exported" Vars into Env first.

From the code I understood that Env should actually satisfy WriteEnviron once a sub shell was created so I was hoping that it was just a bug.

mvdan commented 1 year ago

Then you should call Runner.Run and then look at the Runner.Vars field; Env is generally read-only, so it might not contain all the vars that your sourced script defined.

mattimo commented 1 year ago

I see. Thanks for the explanation! I tried this earlier with a subshell but the vars were also empty but I think I can just use the runner without a subshell and I should be fine for now.

The question if the subshell vars should be empty still remains for me though.

mvdan commented 1 year ago

Yeah, you shouldn't need to use a subshell to source a script. I still agree that Env/Vars works a bit weird with subshells, and I'll leave this issue open for that.