pkgx icon indicating copy to clipboard operation
pkgx copied to clipboard

read the shebang and magically hydrate deps

Open mxcl opened this issue 3 years ago • 4 comments

example usage:

$ sh <(curl tea.xyz) +charm.sh/gum https://github.com/charmbracelet/gum/blob/main/examples/demo.sh

Not a great example, but this demo script requires bash and not just any sh so we install bash, put it in the env and then get sh to reach for bash that way.

mxcl avatar Nov 22 '22 13:11 mxcl

  • Added a new error type: #helpwanted
  • Changed the way we handle shebangs in exec() to be more robust and flexible, including special casing for python 2/3

what-the-diff[bot] avatar Nov 22 '22 13:11 what-the-diff[bot]

k, just realized that we should also support #!/usr/bin/env foo

mxcl avatar Nov 22 '22 13:11 mxcl

Other considerations:

$ curl -O https://gist.githubusercontent.com/i0bj/2b3afbe07a44179250474b5f36e7bd9b/raw/colors.go
$ mv colors.go colors

$ tea ./colors
tea: installed: ~/.tea/go.dev/v1.19.2
error: permission denied (os error 13)

Because we just ask sh to do it this happens. Is this correct? Should we require the user to make the script executable first?

mxcl avatar Nov 22 '22 13:11 mxcl

I think it should work without marking it executable. What we're trying to replicate here, I think, is when you have some script and you want to call it like bash myscript (instead of ./myscript, which will read the shebang)

I tried this diff and it seems to work:

diff --git a/src/app.exec.ts b/src/app.exec.ts
index 657b86a..696d84d 100644
--- a/src/app.exec.ts
+++ b/src/app.exec.ts
@@ -126,11 +126,12 @@ async function exec(ass: RV1, pkgs: PackageSpecification[], opts: {env: boolean}
     if (yaml) pkgs.push(...yaml.pkgs)
 
     if (magic) {
-      const found = await async_flatmap(extract_shebang(ass.path), which)
+      const shebang = await extract_shebang(ass.path)
+      const found = await async_flatmap(shebang, which)
 
       if (found) {
         pkgs.unshift(found)
-        cmd.unshift("/bin/sh")  // `run` is rudimentary so you gotta give it da `sh`
+        cmd.unshift(shebang)
       } else {
         const unshift = (project: string, ...new_args: string[]) => {
           if (!yaml?.pkgs.length) {

but I don't think it properly handles e.g. switches in the shebang. In any case I think it makes more sense to try to exec the script instead of shelling out to /bin/sh.

jonchang avatar Nov 22 '22 17:11 jonchang

Because we just ask sh to do it this happens. Is this correct? Should we require the user to make the script executable first?

I think the answer is no. However, sh ./foo works regardless of execute (but obviously not read) perms.

jhheider avatar Nov 22 '22 21:11 jhheider

Thanks both, good review. I'll make it so it doesn’t need to have the executable bit set.

One remaining thing that I don’t know about is how “shebangs” work exactly. Because eg. deno will run a script without run being specified (as arg1), but only when running as a shebang. There must be something set in the environment be sh that allows deno (et al) to know this.

This only affects our ability to run scripts without special casing eg. deno (and we're moving that info to the pantry anyway, so maybe it doesn't matter).

mxcl avatar Nov 23 '22 13:11 mxcl

Needs tests, but so does everything. We need this to fix a few one-liners we specify as demos so will merge.

mxcl avatar Nov 23 '22 13:11 mxcl