2019-03-13 04:14:30 -07:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2020-11-19 19:12:20 -08:00
|
|
|
"context"
|
2021-01-05 11:12:52 -08:00
|
|
|
"errors"
|
2021-08-01 06:25:15 -07:00
|
|
|
"fmt"
|
2021-08-03 23:46:59 -07:00
|
|
|
"io"
|
2020-10-07 04:32:42 -07:00
|
|
|
"io/ioutil"
|
2021-08-01 06:25:15 -07:00
|
|
|
"log"
|
2020-11-19 19:12:20 -08:00
|
|
|
"net/http"
|
2019-03-13 04:14:30 -07:00
|
|
|
"os"
|
|
|
|
"os/exec"
|
2020-10-01 11:57:02 -07:00
|
|
|
"path/filepath"
|
2019-03-13 04:14:30 -07:00
|
|
|
"runtime"
|
|
|
|
"strings"
|
2021-02-11 04:19:47 -08:00
|
|
|
"sync"
|
2020-12-31 00:39:02 -08:00
|
|
|
"time"
|
2019-03-13 04:14:30 -07:00
|
|
|
|
|
|
|
"github.com/distatus/battery"
|
2021-11-13 14:46:06 -08:00
|
|
|
process "github.com/shirou/gopsutil/v3/process"
|
2019-03-13 04:14:30 -07:00
|
|
|
)
|
|
|
|
|
2020-11-12 00:43:32 -08:00
|
|
|
const (
|
|
|
|
unknown = "unknown"
|
|
|
|
windowsPlatform = "windows"
|
2021-04-24 12:31:56 -07:00
|
|
|
darwinPlatform = "darwin"
|
|
|
|
linuxPlatform = "linux"
|
2020-11-12 00:43:32 -08:00
|
|
|
)
|
|
|
|
|
2021-01-05 04:05:37 -08:00
|
|
|
type commandError struct {
|
|
|
|
err string
|
|
|
|
exitCode int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *commandError) Error() string {
|
|
|
|
return e.err
|
|
|
|
}
|
|
|
|
|
2021-04-12 10:15:36 -07:00
|
|
|
type noBatteryError struct{}
|
|
|
|
|
|
|
|
func (m *noBatteryError) Error() string {
|
|
|
|
return "no battery"
|
|
|
|
}
|
|
|
|
|
2021-01-05 11:12:52 -08:00
|
|
|
type fileInfo struct {
|
|
|
|
parentFolder string
|
|
|
|
path string
|
|
|
|
isDir bool
|
|
|
|
}
|
|
|
|
|
2021-09-21 11:22:59 -07:00
|
|
|
type cache interface {
|
|
|
|
init(home string)
|
|
|
|
close()
|
|
|
|
get(key string) (string, bool)
|
2021-11-23 02:13:32 -08:00
|
|
|
// ttl in minutes
|
|
|
|
set(key, value string, ttl int)
|
2021-09-21 11:22:59 -07:00
|
|
|
}
|
|
|
|
|
2019-03-13 04:14:30 -07:00
|
|
|
type environmentInfo interface {
|
|
|
|
getenv(key string) string
|
2020-10-02 12:50:13 -07:00
|
|
|
getcwd() string
|
|
|
|
homeDir() string
|
2020-10-01 11:57:02 -07:00
|
|
|
hasFiles(pattern string) bool
|
2020-12-01 11:43:30 -08:00
|
|
|
hasFilesInDir(dir, pattern string) bool
|
2020-10-07 04:32:42 -07:00
|
|
|
hasFolder(folder string) bool
|
|
|
|
getFileContent(file string) string
|
2021-09-04 11:32:55 -07:00
|
|
|
getFoldersList(path string) []string
|
2019-03-13 04:14:30 -07:00
|
|
|
getPathSeperator() string
|
2020-10-12 03:53:54 -07:00
|
|
|
getCurrentUser() string
|
2019-03-13 04:14:30 -07:00
|
|
|
isRunningAsRoot() bool
|
|
|
|
getHostName() (string, error)
|
|
|
|
getRuntimeGOOS() string
|
2020-10-21 19:49:14 -07:00
|
|
|
getPlatform() string
|
2021-01-05 04:05:37 -08:00
|
|
|
hasCommand(command string) bool
|
2020-10-16 08:43:02 -07:00
|
|
|
runCommand(command string, args ...string) (string, error)
|
2020-11-12 00:43:32 -08:00
|
|
|
runShellCommand(shell, command string) string
|
2019-03-13 04:14:30 -07:00
|
|
|
lastErrorCode() int
|
2020-12-06 13:03:40 -08:00
|
|
|
executionTime() float64
|
2019-03-13 04:14:30 -07:00
|
|
|
getArgs() *args
|
2021-04-15 02:04:11 -07:00
|
|
|
getBatteryInfo() ([]*battery.Battery, error)
|
2020-09-24 10:11:56 -07:00
|
|
|
getShellName() string
|
2020-11-12 00:43:32 -08:00
|
|
|
getWindowTitle(imageName, windowTitleRegex string) (string, error)
|
2021-11-24 04:47:30 -08:00
|
|
|
getWindowsRegistryKeyValue(regPath, regKey string) (string, error)
|
2021-08-17 23:21:55 -07:00
|
|
|
doGet(url string, timeout int) ([]byte, error)
|
2021-01-05 11:12:52 -08:00
|
|
|
hasParentFilePath(path string) (fileInfo *fileInfo, err error)
|
2021-02-14 23:26:52 -08:00
|
|
|
isWsl() bool
|
2021-04-12 01:58:03 -07:00
|
|
|
stackCount() int
|
2021-05-22 07:50:34 -07:00
|
|
|
getTerminalWidth() (int, error)
|
2021-10-02 22:27:18 -07:00
|
|
|
getCachePath() string
|
2021-09-21 11:22:59 -07:00
|
|
|
cache() cache
|
|
|
|
close()
|
2021-11-16 10:59:42 -08:00
|
|
|
logs() string
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
|
|
|
|
2021-02-11 04:19:47 -08:00
|
|
|
type commandCache struct {
|
2021-09-20 03:46:07 -07:00
|
|
|
commands *concurrentMap
|
2021-02-11 04:19:47 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *commandCache) set(command, path string) {
|
2021-09-20 03:46:07 -07:00
|
|
|
c.commands.set(command, path)
|
2021-02-11 04:19:47 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *commandCache) get(command string) (string, bool) {
|
2021-09-21 22:53:59 -07:00
|
|
|
cmd, found := c.commands.get(command)
|
|
|
|
if !found {
|
|
|
|
return "", false
|
|
|
|
}
|
2021-09-23 13:57:38 -07:00
|
|
|
command, ok := cmd.(string)
|
|
|
|
return command, ok
|
2021-02-11 04:19:47 -08:00
|
|
|
}
|
|
|
|
|
2021-11-10 10:34:26 -08:00
|
|
|
type logType string
|
|
|
|
|
|
|
|
const (
|
|
|
|
Error logType = "error"
|
|
|
|
Debug logType = "debug"
|
|
|
|
)
|
|
|
|
|
2021-11-16 22:16:43 -08:00
|
|
|
type environment struct {
|
|
|
|
args *args
|
|
|
|
cwd string
|
|
|
|
cmdCache *commandCache
|
|
|
|
fileCache *fileCache
|
|
|
|
logBuilder strings.Builder
|
|
|
|
debug bool
|
2021-08-01 06:25:15 -07:00
|
|
|
}
|
|
|
|
|
2021-11-16 22:16:43 -08:00
|
|
|
func (env *environment) init(args *args) {
|
|
|
|
env.args = args
|
|
|
|
env.cmdCache = &commandCache{
|
|
|
|
commands: newConcurrentMap(),
|
2021-08-01 06:25:15 -07:00
|
|
|
}
|
2021-11-16 22:16:43 -08:00
|
|
|
if env.args != nil && *env.args.Debug {
|
|
|
|
env.debug = true
|
|
|
|
log.SetOutput(&env.logBuilder)
|
2021-08-01 06:25:15 -07:00
|
|
|
}
|
2021-11-16 22:16:43 -08:00
|
|
|
env.fileCache = &fileCache{}
|
|
|
|
env.fileCache.init(env.getCachePath())
|
2021-08-01 06:25:15 -07:00
|
|
|
}
|
|
|
|
|
2021-11-16 22:16:43 -08:00
|
|
|
func (env *environment) trace(start time.Time, function string, args ...string) {
|
|
|
|
if !env.debug {
|
2021-08-01 06:25:15 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
elapsed := time.Since(start)
|
2021-08-04 03:52:54 -07:00
|
|
|
trace := fmt.Sprintf("%s duration: %s, args: %s", function, elapsed, strings.Trim(fmt.Sprint(args), "[]"))
|
2021-08-01 06:25:15 -07:00
|
|
|
log.Println(trace)
|
|
|
|
}
|
|
|
|
|
2021-11-16 22:16:43 -08:00
|
|
|
func (env *environment) log(lt logType, function, message string) {
|
|
|
|
if !env.debug {
|
2021-10-20 02:55:53 -07:00
|
|
|
return
|
|
|
|
}
|
2021-11-10 10:34:26 -08:00
|
|
|
trace := fmt.Sprintf("%s: %s\n%s", lt, function, message)
|
2021-10-20 02:55:53 -07:00
|
|
|
log.Println(trace)
|
|
|
|
}
|
|
|
|
|
2019-03-13 04:14:30 -07:00
|
|
|
func (env *environment) getenv(key string) string {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "getenv", key)
|
2021-11-10 10:34:26 -08:00
|
|
|
val := os.Getenv(key)
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Debug, "getenv", val)
|
2021-11-10 10:34:26 -08:00
|
|
|
return val
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
|
|
|
|
2020-10-02 12:50:13 -07:00
|
|
|
func (env *environment) getcwd() string {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "getcwd")
|
2020-10-12 00:04:37 -07:00
|
|
|
if env.cwd != "" {
|
|
|
|
return env.cwd
|
|
|
|
}
|
2020-10-08 10:23:20 -07:00
|
|
|
correctPath := func(pwd string) string {
|
2021-01-07 10:29:34 -08:00
|
|
|
// on Windows, and being case sensitive and not consistent and all, this gives silly issues
|
2021-11-05 01:02:21 -07:00
|
|
|
driveLetter := getCompiledRegex(`^[a-z]:`)
|
|
|
|
return driveLetter.ReplaceAllStringFunc(pwd, strings.ToUpper)
|
2020-10-08 10:23:20 -07:00
|
|
|
}
|
2020-10-10 10:16:58 -07:00
|
|
|
if env.args != nil && *env.args.PWD != "" {
|
2020-10-12 00:04:37 -07:00
|
|
|
env.cwd = correctPath(*env.args.PWD)
|
|
|
|
return env.cwd
|
2020-10-08 10:23:20 -07:00
|
|
|
}
|
2020-10-02 12:50:13 -07:00
|
|
|
dir, err := os.Getwd()
|
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "getcwd", err.Error())
|
2020-10-02 12:50:13 -07:00
|
|
|
return ""
|
|
|
|
}
|
2020-10-12 00:04:37 -07:00
|
|
|
env.cwd = correctPath(dir)
|
|
|
|
return env.cwd
|
2020-10-02 12:50:13 -07:00
|
|
|
}
|
|
|
|
|
2020-10-01 11:57:02 -07:00
|
|
|
func (env *environment) hasFiles(pattern string) bool {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "hasFiles", pattern)
|
2020-10-02 12:50:13 -07:00
|
|
|
cwd := env.getcwd()
|
2020-10-01 11:57:02 -07:00
|
|
|
pattern = cwd + env.getPathSeperator() + pattern
|
|
|
|
matches, err := filepath.Glob(pattern)
|
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "hasFiles", err.Error())
|
2020-10-01 11:57:02 -07:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
return len(matches) > 0
|
|
|
|
}
|
|
|
|
|
2020-12-01 11:43:30 -08:00
|
|
|
func (env *environment) hasFilesInDir(dir, pattern string) bool {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "hasFilesInDir", pattern)
|
2020-12-01 11:43:30 -08:00
|
|
|
pattern = dir + env.getPathSeperator() + pattern
|
|
|
|
matches, err := filepath.Glob(pattern)
|
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "hasFilesInDir", err.Error())
|
2020-12-01 11:43:30 -08:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
return len(matches) > 0
|
|
|
|
}
|
|
|
|
|
2020-10-07 04:32:42 -07:00
|
|
|
func (env *environment) hasFolder(folder string) bool {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "hasFolder", folder)
|
2020-10-07 04:32:42 -07:00
|
|
|
_, err := os.Stat(folder)
|
|
|
|
return !os.IsNotExist(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (env *environment) getFileContent(file string) string {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "getFileContent", file)
|
2020-10-07 04:32:42 -07:00
|
|
|
content, err := ioutil.ReadFile(file)
|
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "getFileContent", err.Error())
|
2020-10-07 04:32:42 -07:00
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return string(content)
|
|
|
|
}
|
|
|
|
|
2021-09-04 11:32:55 -07:00
|
|
|
func (env *environment) getFoldersList(path string) []string {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "getFoldersList", path)
|
2021-09-04 11:32:55 -07:00
|
|
|
content, err := os.ReadDir(path)
|
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "getFoldersList", err.Error())
|
2021-09-04 11:32:55 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
var folderNames []string
|
|
|
|
for _, s := range content {
|
|
|
|
if s.IsDir() {
|
|
|
|
folderNames = append(folderNames, s.Name())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return folderNames
|
|
|
|
}
|
|
|
|
|
2019-03-13 04:14:30 -07:00
|
|
|
func (env *environment) getPathSeperator() string {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "getPathSeperator")
|
2019-03-13 04:14:30 -07:00
|
|
|
return string(os.PathSeparator)
|
|
|
|
}
|
|
|
|
|
2020-10-12 03:53:54 -07:00
|
|
|
func (env *environment) getCurrentUser() string {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "getCurrentUser")
|
2020-10-12 03:53:54 -07:00
|
|
|
user := os.Getenv("USER")
|
|
|
|
if user == "" {
|
|
|
|
user = os.Getenv("USERNAME")
|
|
|
|
}
|
|
|
|
return user
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (env *environment) getHostName() (string, error) {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "getHostName")
|
2019-03-13 04:14:30 -07:00
|
|
|
hostName, err := os.Hostname()
|
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "getHostName", err.Error())
|
2019-03-13 04:14:30 -07:00
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return cleanHostName(hostName), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (env *environment) getRuntimeGOOS() string {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "getRuntimeGOOS")
|
2019-03-13 04:14:30 -07:00
|
|
|
return runtime.GOOS
|
|
|
|
}
|
|
|
|
|
2020-10-16 08:43:02 -07:00
|
|
|
func (env *environment) runCommand(command string, args ...string) (string, error) {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "runCommand", append([]string{command}, args...)...)
|
2021-02-11 04:19:47 -08:00
|
|
|
if cmd, ok := env.cmdCache.get(command); ok {
|
|
|
|
command = cmd
|
2021-01-05 04:05:37 -08:00
|
|
|
}
|
2021-08-03 23:46:59 -07:00
|
|
|
copyAndCapture := func(r io.Reader) ([]byte, error) {
|
|
|
|
var out []byte
|
|
|
|
buf := make([]byte, 1024)
|
|
|
|
for {
|
|
|
|
n, err := r.Read(buf)
|
|
|
|
if n > 0 {
|
|
|
|
d := buf[:n]
|
|
|
|
out = append(out, d...)
|
|
|
|
}
|
|
|
|
if err == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// Read returns io.EOF at the end of file, which is not an error for us
|
|
|
|
if err == io.EOF {
|
|
|
|
err = nil
|
|
|
|
}
|
|
|
|
return out, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
normalizeOutput := func(out []byte) string {
|
|
|
|
return strings.TrimSuffix(string(out), "\n")
|
|
|
|
}
|
|
|
|
cmd := exec.Command(command, args...)
|
|
|
|
var stdout, stderr []byte
|
|
|
|
var stdoutErr, stderrErr error
|
|
|
|
stdoutIn, _ := cmd.StdoutPipe()
|
|
|
|
stderrIn, _ := cmd.StderrPipe()
|
|
|
|
err := cmd.Start()
|
|
|
|
if err != nil {
|
|
|
|
errorStr := fmt.Sprintf("cmd.Start() failed with '%s'", err)
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "runCommand", errorStr)
|
2021-08-03 23:46:59 -07:00
|
|
|
return "", errors.New(errorStr)
|
|
|
|
}
|
|
|
|
// cmd.Wait() should be called only after we finish reading
|
|
|
|
// from stdoutIn and stderrIn.
|
|
|
|
// wg ensures that we finish
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
wg.Add(1)
|
|
|
|
go func() {
|
|
|
|
stdout, stdoutErr = copyAndCapture(stdoutIn)
|
|
|
|
wg.Done()
|
|
|
|
}()
|
|
|
|
stderr, stderrErr = copyAndCapture(stderrIn)
|
|
|
|
wg.Wait()
|
|
|
|
err = cmd.Wait()
|
2020-12-30 11:01:22 -08:00
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "runCommand", err.Error())
|
2021-01-14 12:41:05 -08:00
|
|
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
|
|
|
return "", &commandError{
|
|
|
|
err: exitErr.Error(),
|
|
|
|
exitCode: exitErr.ExitCode(),
|
|
|
|
}
|
|
|
|
}
|
2020-11-19 00:02:51 -08:00
|
|
|
}
|
2021-08-03 23:46:59 -07:00
|
|
|
if stdoutErr != nil || stderrErr != nil {
|
2021-10-20 02:55:53 -07:00
|
|
|
errString := "failed to capture stdout or stderr"
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "runCommand", errString)
|
2021-10-20 02:55:53 -07:00
|
|
|
return "", errors.New(errString)
|
2021-08-03 23:46:59 -07:00
|
|
|
}
|
|
|
|
stderrStr := normalizeOutput(stderr)
|
|
|
|
if len(stderrStr) > 0 {
|
|
|
|
return stderrStr, nil
|
|
|
|
}
|
2021-11-10 10:34:26 -08:00
|
|
|
output := normalizeOutput(stdout)
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Debug, "runCommand", output)
|
2021-11-10 10:34:26 -08:00
|
|
|
return output, nil
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
|
|
|
|
2020-11-12 00:43:32 -08:00
|
|
|
func (env *environment) runShellCommand(shell, command string) string {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "runShellCommand", shell, command)
|
2021-01-05 04:05:37 -08:00
|
|
|
out, _ := env.runCommand(shell, "-c", command)
|
|
|
|
return out
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
|
|
|
|
2021-01-05 04:05:37 -08:00
|
|
|
func (env *environment) hasCommand(command string) bool {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "hasCommand", command)
|
2021-02-11 04:19:47 -08:00
|
|
|
if _, ok := env.cmdCache.get(command); ok {
|
2021-01-05 04:05:37 -08:00
|
|
|
return true
|
|
|
|
}
|
2020-12-27 23:33:58 -08:00
|
|
|
path, err := exec.LookPath(command)
|
2021-01-05 04:05:37 -08:00
|
|
|
if err == nil {
|
2021-02-11 04:19:47 -08:00
|
|
|
env.cmdCache.set(command, path)
|
2021-01-05 04:05:37 -08:00
|
|
|
return true
|
|
|
|
}
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "hasCommand", err.Error())
|
2021-01-05 04:05:37 -08:00
|
|
|
return false
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (env *environment) lastErrorCode() int {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "lastErrorCode")
|
2019-03-13 04:14:30 -07:00
|
|
|
return *env.args.ErrorCode
|
|
|
|
}
|
|
|
|
|
2020-12-06 13:03:40 -08:00
|
|
|
func (env *environment) executionTime() float64 {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "executionTime")
|
2020-12-12 03:54:25 -08:00
|
|
|
if *env.args.ExecutionTime < 0 {
|
|
|
|
return 0
|
|
|
|
}
|
2020-12-06 13:03:40 -08:00
|
|
|
return *env.args.ExecutionTime
|
|
|
|
}
|
|
|
|
|
2019-03-13 04:14:30 -07:00
|
|
|
func (env *environment) getArgs() *args {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "getArgs")
|
2019-03-13 04:14:30 -07:00
|
|
|
return env.args
|
|
|
|
}
|
|
|
|
|
2021-04-15 02:04:11 -07:00
|
|
|
func (env *environment) getBatteryInfo() ([]*battery.Battery, error) {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "getBatteryInfo")
|
2021-09-19 22:01:00 -07:00
|
|
|
batteries, err := battery.GetAll()
|
|
|
|
// actual error, return it
|
|
|
|
if err != nil && len(batteries) == 0 {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "getBatteryInfo", err.Error())
|
2021-09-19 22:01:00 -07:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// there are no batteries found
|
|
|
|
if len(batteries) == 0 {
|
|
|
|
return nil, &noBatteryError{}
|
|
|
|
}
|
|
|
|
// some batteries fail to get retrieved, filter them out if present
|
|
|
|
validBatteries := []*battery.Battery{}
|
|
|
|
for _, batt := range batteries {
|
|
|
|
if batt != nil {
|
|
|
|
validBatteries = append(validBatteries, batt)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
unableToRetrieveBatteryInfo := "A device which does not exist was specified."
|
|
|
|
// when battery info fails to get retrieved but there is at least one valid battery, return it without error
|
|
|
|
if len(validBatteries) > 0 && err != nil && strings.Contains(err.Error(), unableToRetrieveBatteryInfo) {
|
|
|
|
return validBatteries, nil
|
|
|
|
}
|
|
|
|
// another error occurred (possibly unmapped use-case), return it
|
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "getBatteryInfo", err.Error())
|
2021-09-19 22:01:00 -07:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// everything is fine
|
|
|
|
return validBatteries, nil
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
|
|
|
|
2020-09-24 10:11:56 -07:00
|
|
|
func (env *environment) getShellName() string {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "getShellName")
|
2020-12-27 05:59:40 -08:00
|
|
|
if *env.args.Shell != "" {
|
|
|
|
return *env.args.Shell
|
|
|
|
}
|
2020-09-15 04:44:53 -07:00
|
|
|
pid := os.Getppid()
|
2020-10-23 07:36:40 -07:00
|
|
|
p, _ := process.NewProcess(int32(pid))
|
|
|
|
name, err := p.Name()
|
2020-09-24 10:11:56 -07:00
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "getShellName", err.Error())
|
2020-11-12 00:43:32 -08:00
|
|
|
return unknown
|
2020-09-24 10:11:56 -07:00
|
|
|
}
|
2020-11-02 09:43:10 -08:00
|
|
|
if name == "cmd.exe" {
|
|
|
|
p, _ = p.Parent()
|
|
|
|
name, err = p.Name()
|
|
|
|
}
|
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "getShellName", err.Error())
|
2020-11-12 00:43:32 -08:00
|
|
|
return unknown
|
2020-11-02 09:43:10 -08:00
|
|
|
}
|
2020-12-27 10:51:32 -08:00
|
|
|
// Cache the shell value to speed things up.
|
|
|
|
*env.args.Shell = strings.Trim(strings.Replace(name, ".exe", "", 1), " ")
|
|
|
|
return *env.args.Shell
|
2020-09-15 04:44:53 -07:00
|
|
|
}
|
|
|
|
|
2021-08-17 23:21:55 -07:00
|
|
|
func (env *environment) doGet(url string, timeout int) ([]byte, error) {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "doGet", url)
|
2021-08-17 23:21:55 -07:00
|
|
|
ctx, cncl := context.WithTimeout(context.Background(), time.Millisecond*time.Duration(timeout))
|
2020-12-31 00:39:02 -08:00
|
|
|
defer cncl()
|
|
|
|
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
2020-11-19 19:12:20 -08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
response, err := client.Do(request)
|
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "doGet", err.Error())
|
2020-11-19 19:12:20 -08:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
|
|
if err != nil {
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "doGet", err.Error())
|
2020-11-19 19:12:20 -08:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return body, nil
|
|
|
|
}
|
|
|
|
|
2021-01-05 11:12:52 -08:00
|
|
|
func (env *environment) hasParentFilePath(path string) (*fileInfo, error) {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "hasParentFilePath", path)
|
2021-01-05 11:12:52 -08:00
|
|
|
currentFolder := env.getcwd()
|
|
|
|
for {
|
|
|
|
searchPath := filepath.Join(currentFolder, path)
|
|
|
|
info, err := os.Stat(searchPath)
|
|
|
|
if err == nil {
|
|
|
|
return &fileInfo{
|
|
|
|
parentFolder: currentFolder,
|
|
|
|
path: searchPath,
|
|
|
|
isDir: info.IsDir(),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
if !os.IsNotExist(err) {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if dir := filepath.Dir(currentFolder); dir != currentFolder {
|
|
|
|
currentFolder = dir
|
|
|
|
continue
|
|
|
|
}
|
2021-11-16 22:16:43 -08:00
|
|
|
env.log(Error, "hasParentFilePath", err.Error())
|
2021-01-05 11:12:52 -08:00
|
|
|
return nil, errors.New("no match at root level")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-12 01:58:03 -07:00
|
|
|
func (env *environment) stackCount() int {
|
2021-11-16 22:16:43 -08:00
|
|
|
defer env.trace(time.Now(), "stackCount")
|
2021-04-12 01:58:03 -07:00
|
|
|
if *env.args.StackCount < 0 {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return *env.args.StackCount
|
|
|
|
}
|
|
|
|
|
2021-09-21 11:22:59 -07:00
|
|
|
func (env *environment) cache() cache {
|
|
|
|
return env.fileCache
|
|
|
|
}
|
|
|
|
|
|
|
|
func (env *environment) close() {
|
|
|
|
env.fileCache.close()
|
2021-11-16 10:59:42 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (env *environment) logs() string {
|
2021-11-16 22:16:43 -08:00
|
|
|
return env.logBuilder.String()
|
2021-09-21 11:22:59 -07:00
|
|
|
}
|
|
|
|
|
2019-03-13 04:14:30 -07:00
|
|
|
func cleanHostName(hostName string) string {
|
|
|
|
garbage := []string{
|
|
|
|
".lan",
|
|
|
|
".local",
|
2020-10-07 08:14:26 -07:00
|
|
|
".localdomain",
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
|
|
|
for _, g := range garbage {
|
2020-10-07 08:14:26 -07:00
|
|
|
if strings.HasSuffix(hostName, g) {
|
|
|
|
hostName = strings.Replace(hostName, g, "", 1)
|
|
|
|
}
|
2019-03-13 04:14:30 -07:00
|
|
|
}
|
|
|
|
return hostName
|
|
|
|
}
|
2021-10-02 22:27:18 -07:00
|
|
|
|
|
|
|
func returnOrBuildCachePath(path string) string {
|
|
|
|
// validate root path
|
|
|
|
if _, err := os.Stat(path); err != nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
// validate oh-my-posh folder, if non existent, create it
|
|
|
|
cachePath := path + "/oh-my-posh"
|
|
|
|
if _, err := os.Stat(cachePath); err == nil {
|
|
|
|
return cachePath
|
|
|
|
}
|
|
|
|
if err := os.Mkdir(cachePath, 0755); err != nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return cachePath
|
|
|
|
}
|