/
nickolasfox
/
kek
Обзор
Документация
Войти
/
nickolasfox
/
kek
Код
Запросы
0
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
pkg/tools/exec.go
117 строк
3 KB
Nickolas Fox
Make it possible to install over go install call
29 мар 2024, 20:27
29 мар 2024, 20:27
1a1d55c
Код
Авторство
О чём код?
package tools import ( "bufio" "os" "os/exec" "path" "strings" "unicode" ) const ( // shebangPrefixLen `#!` shebangPrefixLen = 2 // MINGW64 keeps mingw64 environment value, which designates relation to MinGW environment. MINGW64 = "MINGW64" ) var ( lookPath = exec.LookPath shells = []string{"sh", "bash", "ash", "zsh", "fish"} ) // lookPathFunc reflects exec.LookPath function signature. type lookPathFunc = func(file string) (string, error) type runtimeEnvironmentType string const ( runtimeMinGW = "mingw" runtimeUnknown = "unknown" ) // lookPathWithExt provides looking path for executable. func lookPathWithExt(raw string, exts []string) string { if executable, err := lookPath(raw); err == nil { return executable } executable := raw for _, ext := range exts { if e, err := lookPath(raw + "." + ext); err == nil { executable = e break } } return executable } // isShell detects if raw executable is kind of shell application func isShell(raw string) (is bool) { for _, sh := range shells { is = strings.HasSuffix(raw, sh) if is { break } } return } // runtimeEnvironment should detect an environment where application has been run. // for example, there might be no bash[.exe] accessible using cmd.exe or powershell, // rather than mingw/cygwin/etc. provides assets to detect their place. func runtimeEnvironment() runtimeEnvironmentType { if env := os.Getenv("MSYSTEM"); env == MINGW64 { return runtimeMinGW } return runtimeUnknown } // PopExecutable reads executable path from raw and transform it for different environments. // Supported environments: // - Windows MiniGW (git for windows) func PopExecutable(raw string) string { if !isShell(raw) { return lookPathWithExt(raw, extensions()) } switch runtimeEnvironment() { case runtimeMinGW: exePath := os.Getenv("EXEPATH") executable := path.Base(raw) return NormPath(path.Join(exePath, executable)) default: // log -> unknown return raw } } // ShellExec reads a text file and returns its executable and arguments on success. // Note, that ShellExec is ok to run over already verified text files. If your file // binary -> you might suffer extra memory consumption for the reason of no new line // separator would be found. func ShellExec(location string) (executable string, preArgs []string, err error) { var fd *os.File if fd, err = os.Open(location); err != nil { return } defer Close(fd) scanner := bufio.NewScanner(fd) scanner.Scan() line := scanner.Text() // TODO: what if there's no shebang? if strings.HasPrefix(line, "#!") { parts := strings.FieldsFunc(line, func(r rune) bool { return unicode.IsSpace(r) }) executable = PopExecutable(parts[0][shebangPrefixLen:]) if len(parts) > 1 { preArgs = parts[1:] } } return }