2024-06-02 11:32:17 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-09-07 09:06:06 +02:00
|
|
|
"encoding/json"
|
2024-06-02 11:32:17 +02:00
|
|
|
"fmt"
|
2024-06-03 01:04:47 +02:00
|
|
|
"io"
|
2024-06-02 11:32:17 +02:00
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/alexflint/go-arg"
|
|
|
|
)
|
|
|
|
|
|
|
|
var version string // to be set by compiler
|
|
|
|
|
|
|
|
var args struct {
|
|
|
|
File string `arg:"positional" help:"if not specified, will read from stdin" default:""`
|
|
|
|
Outfile string `arg:"positional" help:"if not specified, will emit to stdout" default:""`
|
|
|
|
Version bool `arg:"-v" help:"print version and exit"`
|
2024-09-07 09:06:06 +02:00
|
|
|
YieldDepsOnly bool `arg:"--yield-deps-only" help:"print dependencies as a JSON array and exit" default:"false"`
|
|
|
|
ExposeDeps bool `arg:"--expose-deps" help:"expose dependencies to program" default:"false"`
|
2024-06-02 11:32:17 +02:00
|
|
|
DepsVarName string `arg:"--deps-var-name" help:"override deps variable name" default:"deps"`
|
2024-09-07 09:06:06 +02:00
|
|
|
IgnoreShebang bool `arg:"--ignore-shebang" help:"ignore shebang requirement" default:"false"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func emit(code string) {
|
|
|
|
if args.Outfile == "" {
|
|
|
|
fmt.Printf("%s", code)
|
|
|
|
} else {
|
|
|
|
os.WriteFile(args.Outfile, []byte(code), os.FileMode(0o755))
|
|
|
|
}
|
2024-06-02 11:32:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
arg.MustParse(&args)
|
|
|
|
if args.Version {
|
|
|
|
fmt.Println(version)
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
var file []byte
|
2024-06-03 01:06:03 +02:00
|
|
|
if (args.File != "") && (args.File != "-") {
|
2024-06-02 11:32:17 +02:00
|
|
|
f, err := os.ReadFile(args.File)
|
|
|
|
if err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
fmt.Fprintf(os.Stderr, "File %s does not exist!", args.File)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
file = f
|
|
|
|
} else {
|
2024-06-03 01:04:47 +02:00
|
|
|
data, err := io.ReadAll(os.Stdin)
|
2024-06-02 11:32:17 +02:00
|
|
|
|
2024-06-03 01:04:47 +02:00
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Coudln't read from stdin: %s", err.Error())
|
|
|
|
os.Exit(1)
|
2024-06-02 11:32:17 +02:00
|
|
|
}
|
2024-06-03 01:04:47 +02:00
|
|
|
file = data
|
2024-06-02 11:32:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
code := string(file)
|
|
|
|
found, err := find(code)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2024-09-07 09:06:06 +02:00
|
|
|
if args.YieldDepsOnly {
|
|
|
|
marshaled, err := json.Marshal(found)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
if string(marshaled) == "null" {
|
|
|
|
emit("[]")
|
|
|
|
} else {
|
|
|
|
emit(string(marshaled))
|
|
|
|
}
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(found) == 0 {
|
|
|
|
emit(code)
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
2024-06-02 11:32:17 +02:00
|
|
|
codelines := strings.Split(code, "\n")
|
|
|
|
|
|
|
|
if len(codelines) < 2 {
|
|
|
|
fmt.Fprintf(os.Stderr, "The code must have at least two lines!\n")
|
|
|
|
os.Exit(3)
|
|
|
|
}
|
|
|
|
|
|
|
|
shebang := codelines[0]
|
|
|
|
|
|
|
|
if !((shebang == "#!/bin/bash") || (shebang == "#!/usr/bin/env bash")) && (!args.IgnoreShebang) {
|
|
|
|
fmt.Fprintf(os.Stderr, "The code must start with one of those shebangs: #!/bin/bash OR #!/usr/bin/env bash\n")
|
|
|
|
os.Exit(2)
|
|
|
|
}
|
|
|
|
|
2024-06-03 01:04:47 +02:00
|
|
|
gen := shebang + "\n\n" + gencode(found) + "\n\n" + strings.Join(codelines[1:], "\n")
|
2024-09-07 09:06:06 +02:00
|
|
|
emit(gen)
|
2024-06-02 11:32:17 +02:00
|
|
|
}
|