123 lines
3.1 KiB
Go
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
|
|
}
|