|
|
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !plan9
package main
import ( "bufio" "context" "fmt" "os" "os/user" "path/filepath" "runtime" "strings" )
const ( bashConfig = ".bash_profile" zshConfig = ".zshrc" )
// appendToPATH adds the given path to the PATH environment variable and
// persists it for future sessions.
func appendToPATH(value string) error { if isInPATH(value) { return nil } return persistEnvVar("PATH", pathVar+envSeparator+value) }
func isInPATH(dir string) bool { p := os.Getenv("PATH")
paths := strings.Split(p, envSeparator) for _, d := range paths { if d == dir { return true } }
return false }
func getHomeDir() (string, error) { home := os.Getenv(homeKey) if home != "" { return home, nil }
u, err := user.Current() if err != nil { return "", err } return u.HomeDir, nil }
func checkStringExistsFile(filename, value string) (bool, error) { file, err := os.OpenFile(filename, os.O_RDONLY, 0600) if err != nil { if os.IsNotExist(err) { return false, nil } return false, err } defer file.Close()
scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() if line == value { return true, nil } }
return false, scanner.Err() }
func appendToFile(filename, value string) error { verbosef("Adding %q to %s", value, filename)
ok, err := checkStringExistsFile(filename, value) if err != nil { return err } if ok { // Nothing to do.
return nil }
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) if err != nil { return err } defer f.Close()
_, err = f.WriteString(lineEnding + value + lineEnding) return err }
func isShell(name string) bool { return strings.Contains(currentShell(), name) }
// persistEnvVarWindows sets an environment variable in the Windows
// registry.
func persistEnvVarWindows(name, value string) error { _, err := runCommand(context.Background(), "powershell", "-command", fmt.Sprintf(`[Environment]::SetEnvironmentVariable("%s", "%s", "User")`, name, value)) return err }
func persistEnvVar(name, value string) error { if runtime.GOOS == "windows" { if err := persistEnvVarWindows(name, value); err != nil { return err }
if isShell("cmd.exe") || isShell("powershell.exe") { return os.Setenv(strings.ToUpper(name), value) } // User is in bash, zsh, etc.
// Also set the environment variable in their shell config.
}
rc, err := shellConfigFile() if err != nil { return err }
line := fmt.Sprintf("export %s=%s", strings.ToUpper(name), value) if err := appendToFile(rc, line); err != nil { return err }
return os.Setenv(strings.ToUpper(name), value) }
func shellConfigFile() (string, error) { home, err := getHomeDir() if err != nil { return "", err }
switch { case isShell("bash"): return filepath.Join(home, bashConfig), nil case isShell("zsh"): return filepath.Join(home, zshConfig), nil default: return "", fmt.Errorf("%q is not a supported shell", currentShell()) } }
|