badger/internal/executables/all.go
2023-03-14 09:53:33 +01:00

123 lines
3.1 KiB
Go

package executables
import (
"embed"
"errors"
"io"
"io/fs"
"os/exec"
"path"
"strings"
"velvettear/badger/internal/log"
)
const FFPROBE = "ffprobe"
const FPCALC = "fpcalc"
var MandatoryExecutables []string
var Executables []Executable
// exported function(s)
func Initialize(mandatoryExecutables ...string) {
if len(mandatoryExecutables) == 0 {
MandatoryExecutables = []string{FFPROBE, FPCALC}
} else {
MandatoryExecutables = mandatoryExecutables
}
Executables = locateSystemExecutables()
}
func GetExecutable(executableName string) (Executable, error) {
for _, executable := range Executables {
if strings.ToLower(executable.Name) == strings.ToLower(executableName) {
return executable, nil
}
}
return Executable{}, errors.New("executable '" + executableName + "' is unavailable")
}
func GetMissingExecutables() []string {
missingExecutables := []string{}
for _, mandatoryExecutableName := range MandatoryExecutables {
mandatoryExecutableName = strings.ToLower(mandatoryExecutableName)
for _, availableExecutable := range Executables {
availableExecutableName := strings.ToLower(availableExecutable.Name)
if strings.Contains(availableExecutableName, mandatoryExecutableName) {
continue
}
}
missingExecutables = append(missingExecutables, mandatoryExecutableName)
}
return missingExecutables
}
func ExportExecutables(embeddedFS *embed.FS) {
error := fs.WalkDir(embeddedFS, ".", func(file string, entry fs.DirEntry, error error) error {
if entry.IsDir() || file == "." {
return nil
}
executable, error := exportThirdPartyExecutable(embeddedFS, path.Base(file))
if error != nil {
return error
}
Executables = append(Executables, executable)
return nil
})
if error != nil {
log.Fatal("encountered one or more errors exporting third party executables", error.Error())
}
}
func AreMandatoryExecutablesAvailable() bool {
for {
mandatoryExecutable := MandatoryExecutables[0]
for _, availableExecutable := range Executables {
if availableExecutable.Name != mandatoryExecutable {
continue
}
MandatoryExecutables = MandatoryExecutables[1:]
break
}
if len(MandatoryExecutables) == 0 {
break
}
}
return len(MandatoryExecutables) == 0
}
func (executable Executable) Spawn(arguments ...string) (string, error) {
return spawnProcess(executable.Path, arguments...)
}
func spawnProcess(command string, arguments ...string) (string, error) {
cmd := exec.Command(command, arguments...)
stdout, stdoutError := cmd.StdoutPipe()
stderr, stderrError := cmd.StderrPipe()
cmd.Start()
if stdoutError != nil {
return "", stdoutError
}
if stderrError != nil {
return "", stderrError
}
resultBytes, stdoutError := io.ReadAll(stdout)
if stdoutError != nil {
return "", stdoutError
}
errorBytes, stderrError := io.ReadAll(stderr)
if stderrError != nil {
return "", stderrError
}
cmd.Wait()
error := strings.Trim(string(errorBytes), "\n")
if len(error) > 0 {
return "", errors.New(error)
}
return strings.Trim(string(resultBytes), "\n"), nil
}
// struct(s)
type Executable struct {
Name string
Path string
}