github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/internal/osutils/osutils.go (about)

     1  package osutils
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/exec"
     7  	"path"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"github.com/ActiveState/cli/internal/errs"
    12  	"github.com/ActiveState/cli/internal/fileutils"
    13  	"github.com/ActiveState/cli/internal/multilog"
    14  )
    15  
    16  // CmdString returns a human-readable description of c.
    17  // This is a copy of the Go 1.13 (cmd.String) function
    18  func CmdString(c *exec.Cmd) string {
    19  
    20  	// report the exact executable path (plus args)
    21  	b := new(strings.Builder)
    22  	b.WriteString(c.Path)
    23  
    24  	for _, a := range c.Args[1:] {
    25  		b.WriteByte(' ')
    26  		b.WriteString(a)
    27  	}
    28  
    29  	return b.String()
    30  }
    31  
    32  // BashifyPath takes a windows style path and turns it into a bash style path
    33  // eg. C:\temp becomes /c/temp
    34  func BashifyPath(absolutePath string) (string, error) {
    35  	if absolutePath[0:1] == "/" {
    36  		// Already the format we want
    37  		return absolutePath, nil
    38  	}
    39  
    40  	if absolutePath[1:2] != ":" {
    41  		// Check for windows style paths
    42  		return "", errs.New("Unrecognized absolute path format: %s", absolutePath)
    43  	}
    44  
    45  	winPath, err := winPathToLinPath(absolutePath)
    46  	if err == nil {
    47  		winPath = strings.Replace(winPath, ` `, `\ `, -1) // escape space
    48  		return winPath, nil
    49  	}
    50  	multilog.Error("Failed to bashify path using installed bash executable, falling back to slash replacement: %v", err)
    51  
    52  	vol := filepath.VolumeName(absolutePath)
    53  	absolutePath = absolutePath[len(vol):]
    54  	vol = strings.Replace(vol, ":", "", 1)
    55  	winPath = "/" + vol + filepath.ToSlash(absolutePath)
    56  	winPath = strings.Replace(winPath, ` `, `\ `, -1) // escape space
    57  	return winPath, nil
    58  }
    59  
    60  func winPathToLinPath(name string) (string, error) {
    61  	cmd := exec.Command("bash", "-c", "pwd")
    62  	cmd.Dir = filepath.Dir(name)
    63  
    64  	out, err := cmd.Output()
    65  	if err != nil {
    66  		return "", err
    67  	}
    68  
    69  	path := strings.TrimSpace(string(out)) + "/" + filepath.Base(name)
    70  
    71  	return path, nil
    72  }
    73  
    74  // Getwd is an alias of os.Getwd which wraps the error in our localized error message and FailGetWd, which is user facing (doesn't get logged)
    75  func Getwd() (string, error) {
    76  	r, err := os.Getwd()
    77  	if err != nil {
    78  		return "", errs.Wrap(err, "GetWd failed")
    79  	}
    80  	return r, nil
    81  }
    82  
    83  func EnvSliceToMap(envSlice []string) map[string]string {
    84  	env := map[string]string{}
    85  	for _, v := range envSlice {
    86  		kv := strings.SplitN(v, "=", 2)
    87  		env[kv[0]] = ""
    88  		if len(kv) == 2 { // account for empty values, windows does some weird stuff, better safe than sorry
    89  			env[kv[0]] = kv[1]
    90  		}
    91  	}
    92  	return env
    93  }
    94  
    95  func EnvMapToSlice(envMap map[string]string) []string {
    96  	var env []string
    97  	for k, v := range envMap {
    98  		env = append(env, fmt.Sprintf("%s=%s", k, v))
    99  	}
   100  
   101  	return env
   102  }
   103  
   104  // Executable returns the resolved path to the currently running executable.
   105  func Executable() string {
   106  	exec, err := os.Executable()
   107  	if err != nil {
   108  		exec = os.Args[0]
   109  	}
   110  
   111  	resolved, err := fileutils.ResolvePath(exec)
   112  	if err != nil {
   113  		return exec
   114  	}
   115  
   116  	return resolved
   117  }
   118  
   119  // ExecutableName returns the name of the executable called with the extension
   120  // removed and falls back to the command used to call the executable.
   121  func ExecutableName() string {
   122  	name := filepath.Base(Executable())
   123  	name = strings.TrimSuffix(name, path.Ext(name))
   124  	return name
   125  }