bugfixes for windows and git bash

This commit is contained in:
AJ ONeal 2019-07-28 05:03:44 -06:00
parent e2b9cef690
commit 964972846a
8 changed files with 56 additions and 47 deletions

View File

@ -6,6 +6,8 @@ Manage PATH on Windows, Mac, and Linux with various Shells
pathman list pathman list
pathman add ~/.local/bin pathman add ~/.local/bin
pathman remove ~/.local/bin pathman remove ~/.local/bin
pathman version
pathman help
``` ```
Windows: stores PATH in the registry. Windows: stores PATH in the registry.
@ -109,7 +111,7 @@ curl https://rootprojects.org/pathman/dist/linux/armv5/pathman -o pathman
``` ```
mkdir %userprofile%\bin mkdir %userprofile%\bin
move pathman.exe %userprofile%\bin\pathman.exe move pathman.exe %userprofile%\bin\pathman.exe
%userprofile%\bin\pathman.exe ~\bin %userprofile%\bin\pathman.exe add ~\bin
``` ```
**All Others** **All Others**

View File

@ -69,10 +69,11 @@ func initializeShells(home string) error {
var hasRC bool var hasRC bool
var nativeMatch *envConfig var nativeMatch *envConfig
shell := strings.TrimSuffix(filepath.Base(os.Getenv("SHELL")), ".exe")
for i := range confs { for i := range confs {
c := confs[i] c := confs[i]
if filepath.Base(os.Getenv("SHELL")) == c.shell { if shell == c.shell {
nativeMatch = c nativeMatch = c
} }
@ -103,7 +104,7 @@ func initializeShells(home string) error {
} }
// MacOS is special. It *requires* .bash_profile in order to read .bashrc // MacOS is special. It *requires* .bash_profile in order to read .bashrc
if "darwin" == runtime.GOOS && "bash" == os.Getenv("SHELL") { if "darwin" == runtime.GOOS && "bash" == shell {
if err := ensureBashProfile(home); nil != err { if err := ensureBashProfile(home); nil != err {
return err return err
} }

View File

@ -46,36 +46,10 @@ func main() {
entry = os.Args[2] entry = os.Args[2]
} }
// https://superuser.com/a/69190/73857
// https://github.com/rust-lang-nursery/rustup.rs/issues/686#issuecomment-253982841
// exec source $HOME/.profile
shell := os.Getenv("SHELL")
shell = filepath.Base(shell)
switch shell {
case "":
if strings.HasSuffix(os.Getenv("COMSPEC"), "/cmd.exe") {
shell = "cmd"
}
case "fish":
// ignore
case "zsh":
// ignore
case "bash":
// ignore
default:
// warn and try anyway
fmt.Fprintf(
os.Stderr,
"%q isn't a recognized shell. Please open an issue at https://git.rootprojects.org/root/pathman/issues?q=%s",
shell,
shell,
)
}
home, _ := os.UserHomeDir() home, _ := os.UserHomeDir()
if "" != entry && '~' == entry[0] { if "" != entry && '~' == entry[0] {
// Let windows users not to have to type %USERPROFILE% or \Users\me every time // Let windows users not to have to type %USERPROFILE% or \Users\me every time
entry = strings.Replace(entry, "~", home, 0) entry = strings.Replace(entry, "~", home, 1)
} }
switch action { switch action {
default: default:
@ -92,8 +66,10 @@ func main() {
} }
list() list()
case "add": case "add":
checkShell()
add(entry) add(entry)
case "remove": case "remove":
checkShell()
remove(entry) remove(entry)
} }
} }
@ -157,7 +133,7 @@ func add(entry string) {
modified, err := addPath(entry) modified, err := addPath(entry)
if nil != err { if nil != err {
fmt.Fprintf(os.Stderr, "failed to add %q to PATH: %s", entry, err) fmt.Fprintf(os.Stderr, "%sfailed to add %q to PATH: %s", pathstore, entry, err)
os.Exit(1) os.Exit(1)
} }
@ -223,6 +199,38 @@ func remove(entry string) {
fmt.Println(msg + "\n") fmt.Println(msg + "\n")
} }
// warns if this is an unknown / untested shell
func checkShell() {
// https://superuser.com/a/69190/73857
// https://github.com/rust-lang-nursery/rustup.rs/issues/686#issuecomment-253982841
// exec source $HOME/.profile
shellexe := filepath.Base(os.Getenv("SHELL"))
shell := strings.TrimSuffix(shellexe, ".exe")
switch shell {
case ".":
shell = ""
fallthrough
case "":
if strings.HasSuffix(os.Getenv("COMSPEC"), "\\cmd.exe") {
shell = "cmd"
}
case "fish":
// ignore
case "zsh":
// ignore
case "bash":
// ignore
default:
// warn and try anyway
fmt.Fprintf(
os.Stderr,
"%q isn't a recognized shell. Please open an issue at https://git.rootprojects.org/root/pathman/issues?q=%s\n",
shellexe,
shellexe,
)
}
}
// Paths returns path entries in the current environment // Paths returns path entries in the current environment
func Paths() []string { func Paths() []string {
cur := os.Getenv("PATH") cur := os.Getenv("PATH")
@ -242,7 +250,7 @@ func Paths() []string {
// path entry to the current shell session // path entry to the current shell session
func Add(p string) string { func Add(p string) string {
if isCmdExe() { if isCmdExe() {
return fmt.Sprintf(`PATH %s;%PATH%`, p) return fmt.Sprintf(`PATH %s;%%PATH%%`, strings.Replace(p, "%", "%%", -1))
} }
return fmt.Sprintf(`export PATH="%s:$PATH"`, p) return fmt.Sprintf(`export PATH="%s:$PATH"`, p)
} }
@ -257,5 +265,5 @@ func Remove(entries []string) string {
} }
func isCmdExe() bool { func isCmdExe() bool {
return "" == os.Getenv("SHELL") && strings.Contains(strings.ToLower(os.Getenv("COMSPEC")), "/cmd.exe") return "" == os.Getenv("SHELL") && strings.HasSuffix(strings.ToLower(os.Getenv("COMSPEC")), "\\cmd.exe")
} }

View File

@ -6,6 +6,8 @@ import (
"git.rootprojects.org/root/pathman/envpath" "git.rootprojects.org/root/pathman/envpath"
) )
var pathstore = ""
func addPath(p string) (bool, error) { func addPath(p string) (bool, error) {
return envpath.Add(p) return envpath.Add(p)
} }

View File

@ -6,6 +6,8 @@ import (
"git.rootprojects.org/root/pathman/winpath" "git.rootprojects.org/root/pathman/winpath"
) )
var pathstore = "[winpath] "
func addPath(p string) (bool, error) { func addPath(p string) (bool, error) {
return winpath.Add(p) return winpath.Add(p)
} }

View File

@ -56,7 +56,7 @@ func NormalizePathEntry(pathentry string) (string, string) {
if strings.HasPrefix(strings.ToLower(absentry)+sep, strings.ToLower(home)+sep) { if strings.HasPrefix(strings.ToLower(absentry)+sep, strings.ToLower(home)+sep) {
// %USERPROFILE% is allowed, but only for user PATH // %USERPROFILE% is allowed, but only for user PATH
// https://superuser.com/a/442163/73857 // https://superuser.com/a/442163/73857
homeentry = `%USERPROFILE%` + pathentry[len(home):] homeentry = `%USERPROFILE%` + absentry[len(home):]
} }
if absentry == pathentry { if absentry == pathentry {

View File

@ -1,4 +1,4 @@
// +build windows,unsafe // +build windows,!nounsafe
package winpath package winpath

View File

@ -29,12 +29,6 @@ func add(p string) (bool, error) {
return false, nil return false, nil
} }
k, err := registry.OpenKey(registry.CURRENT_USER, `Environment`, registry.SET_VALUE)
if err != nil {
return false, err
}
defer k.Close()
cur = append([]string{p}, cur...) cur = append([]string{p}, cur...)
err = write(cur) err = write(cur)
if nil != err { if nil != err {
@ -63,7 +57,7 @@ func remove(p string) (bool, error) {
} }
} }
err = write(cur) err = write(newpaths)
if nil != err { if nil != err {
return false, err return false, err
} }
@ -74,15 +68,15 @@ func remove(p string) (bool, error) {
func write(cur []string) error { func write(cur []string) error {
// TODO --system to add to the system PATH rather than the user PATH // TODO --system to add to the system PATH rather than the user PATH
k, err := registry.OpenKey(registry.CURRENT_USER, `Environment`, registry.QUERY_VALUE) k, err := registry.OpenKey(registry.CURRENT_USER, `Environment`, registry.SET_VALUE)
if err != nil { if err != nil {
return err return fmt.Errorf("Can't open HKCU Environment for writes: %s", err)
} }
defer k.Close() defer k.Close()
err = k.SetStringValue(`Path`, strings.Join(cur, string(os.PathListSeparator))) err = k.SetStringValue(`Path`, strings.Join(cur, string(os.PathListSeparator)))
if nil != err { if nil != err {
return err return fmt.Errorf("Can't set HKCU Environment[Path]: %s", err)
} }
err = k.Close() err = k.Close()
@ -104,7 +98,7 @@ func paths() ([]string, error) {
// TBH, it's a mess to do this on *nix systems. // TBH, it's a mess to do this on *nix systems.
k, err := registry.OpenKey(registry.CURRENT_USER, `Environment`, registry.QUERY_VALUE) k, err := registry.OpenKey(registry.CURRENT_USER, `Environment`, registry.QUERY_VALUE)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("Can't open HKCU Environment for reads: %s", err)
} }
defer k.Close() defer k.Close()
@ -112,7 +106,7 @@ func paths() ([]string, error) {
// PATH, Path, path will all work. // PATH, Path, path will all work.
s, _, err := k.GetStringValue("Path") s, _, err := k.GetStringValue("Path")
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("Can't query HKCU Environment[Path]: %s", err)
} }
// ";" on Windows // ";" on Windows