pantry/scripts/brewkit/fix-shebangs.ts

74 lines
1.7 KiB
TypeScript
Raw Normal View History

2022-09-13 16:18:47 +03:00
#!/usr/bin/env -S tea -E
/* ---
args:
- deno
- run
- --allow-run
- --allow-env
- --allow-read
- --allow-write={{tea.prefix}}
--- */
2022-09-20 14:53:40 +03:00
import Path from "path"
2022-09-13 16:18:47 +03:00
import { undent } from "utils"
2022-09-20 14:53:40 +03:00
import { useFlags } from "hooks"
2022-09-13 16:18:47 +03:00
useFlags()
const has_shebang = (() => {
const encoder = new TextDecoder()
return (buf: Uint8Array) => {
return encoder.decode(buf) == '#!'
}
})()
for (const path of Deno.args) {
if (!Path.cwd().join(path).isFile()) continue
console.debug({ path })
const rid = await Deno.open(path, { read: true })
try {
const buf = new Uint8Array(2)
await rid.read(buf)
if (!has_shebang(buf)) continue
} finally {
rid.close()
}
//FIXME this could be pretty damn efficient if we can find the time
//NOTE as it stands this is HIDEOUSLY inefficient
const contents = await Deno.readFile(path)
const txt = new TextDecoder().decode(contents)
const [line0, ...lines] = txt.split("\n") //lol
const match = line0.match(/^#!\s*(\/[^\s]+)/)
2022-09-18 19:01:10 +03:00
if (!match) throw new Error()
const interpreter = match[1]
switch (interpreter) {
case "/usr/bin/env":
case "/bin/sh":
console.verbose({ line0, path })
console.verbose("^^ skipped acceptable shebang")
continue
2022-09-13 16:18:47 +03:00
}
2022-09-18 19:01:10 +03:00
const shebang = `#!/usr/bin/env ${new Path(interpreter).basename()}`
2022-09-13 16:18:47 +03:00
const rewrite = undent`
${shebang}
${lines.join("\n")}
`
console.verbose({rewrote: path, to: `#!/usr/bin/env ${interpreter}`})
const stat = Deno.lstatSync(path)
const needs_chmod = stat.mode && !(stat.mode & 0o200)
if (needs_chmod) Deno.chmodSync(path, 0o666)
2022-09-13 16:18:47 +03:00
await Deno.writeFile(path, new TextEncoder().encode(rewrite))
if (needs_chmod) Deno.chmodSync(path, stat.mode!)
2022-09-13 16:18:47 +03:00
}