add remove

This commit is contained in:
AJ ONeal 2019-07-21 20:32:34 -06:00
parent a48617eaa8
commit 0a5f44eca7
1 changed files with 95 additions and 100 deletions

View File

@ -3,12 +3,10 @@ package main
import (
"fmt"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"strconv"
"strings"
"time"
)
// ppsep is used as the replacement for slashes in path
@ -25,7 +23,8 @@ import (
const ppsep = "-"
func usage() {
fmt.Fprintf(os.Stderr, "Usage: envpath show|add|append|remove <path>\n")
//fmt.Fprintf(os.Stderr, "Usage: envpath show|add|append|remove <path>\n")
fmt.Fprintf(os.Stderr, "Usage: envpath show|add|remove <path>\n")
}
func main() {
@ -38,11 +37,7 @@ func main() {
}
action := os.Args[1]
paths, err := Paths()
if nil != err {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(2)
}
paths := Paths()
if "show" == action {
if len(os.Args) > 2 {
@ -79,16 +74,18 @@ func main() {
default:
usage()
os.Exit(1)
case "append":
newpath, _, err := addPath(pathentry, appendOrder)
if nil != err {
fmt.Fprintf(os.Stderr, "%s\n", err)
return
}
fmt.Println("New sessions will have " + pathentry + " in their PATH.")
fmt.Println("To update this session run\n")
//fmt.Println("\tsource", pathfile)
fmt.Printf(`%sexport PATH="$PATH:%s"%s`, "\t", newpath, "\n")
/*
case "append":
newpath, _, err := addPath(pathentry, appendOrder)
if nil != err {
fmt.Fprintf(os.Stderr, "%s\n", err)
return
}
fmt.Println("New sessions will have " + pathentry + " in their PATH.")
fmt.Println("To update this session run\n")
//fmt.Println("\tsource", pathfile)
fmt.Printf(`%sexport PATH="$PATH:%s"%s`, "\t", newpath, "\n")
*/
case "add":
_, pathfile, err := addPath(pathentry, prependOrder)
if nil != err {
@ -99,27 +96,19 @@ func main() {
fmt.Printf("\tsource %s\n\n", pathfile)
//fmt.Printf(`%sexport PATH="%s:$PATH"%s`, "\t", newpath, "\n\n")
case "remove":
_, err := removePath(pathentry)
msg, err := removePath(pathentry)
if nil != err {
fmt.Fprintf(os.Stderr, "%s\n", err)
return
}
fmt.Println(msg)
}
// TODO support both of these usages:
// 1. export PATH="$(envpath append /opt/whatever/bin)"
// 2. envpath append /opt/whatever/bin
// export PATH="$PATH:/opt/whatever/bin"
}
// Paths returns the slice of PATHs from the Environment
func Paths() ([]string, error) {
func Paths() []string {
// ":" on *nix
return strings.Split(os.Getenv("PATH"), string(os.PathListSeparator)), nil
}
func init() {
rand.Seed(time.Now().UnixNano())
return strings.Split(os.Getenv("PATH"), string(os.PathListSeparator))
}
type setOrder bool
@ -168,8 +157,12 @@ func addPath(oldpathentry string, order setOrder) (string, string, error) {
return "", "", err
}
if err := ensureNotInPath(home, pathentry); nil != err {
return "", "", err
if index, ok := isInPath(home, pathentry); ok {
return "", "", fmt.Errorf(
"%q is in your PATH at position %d and must be removed manually to re-order\n",
pathentry,
index,
)
}
// ex: 100-opt»foo»bin.sh
@ -189,12 +182,76 @@ func addPath(oldpathentry string, order setOrder) (string, string, error) {
return pathentry, fullname, nil
}
// TODO don't check in parser before add/append functions actually run
func ensureNotInPath(home, pathentry string) error {
paths, err := Paths()
func removePath(oldpathentry string) (string, error) {
home, err := os.UserHomeDir()
if nil != err {
return err
return "", err
}
home = filepath.ToSlash(home)
pathentry, fname, err := normalizeEntryAndFile(home, oldpathentry)
if nil != err {
return "", err
}
envpathd := filepath.Join(home, ".config/envpath/path.d")
err = os.MkdirAll(envpathd, 0755)
if nil != err {
return "", err
}
nodes, err := ioutil.ReadDir(envpathd)
if nil != err {
return "", err
}
var fullname string
for i := range nodes {
node := nodes[i]
// 000-foo-bin.sh vs foo-bin.sh
if strings.HasSuffix(node.Name(), "-"+fname) {
if len(strings.Split(node.Name(), "-"))-1 == len(strings.Split(fname, "-")) {
fullname = node.Name()
}
}
}
paths := Paths()
index, exists := isInPath(home, pathentry)
if "" == fullname {
if exists {
return "", fmt.Errorf("%q is in your PATH, but is NOT managed by envpath", pathentry)
}
return "", fmt.Errorf("%q is NOT in your PATH, and NOT managed by envpath", pathentry)
}
err = os.Remove(filepath.Join(envpathd, fullname))
if nil != err {
return "", err
}
if !exists {
return fmt.Sprintf("Removed %s", filepath.Join(envpathd, fullname)), nil
}
newpaths := []string{}
for i := range paths {
if i == index {
continue
}
newpaths = append(newpaths, paths[i])
}
return fmt.Sprintf(
"Removed %s. To update the current shell re-export the new PATH:\n\n"+
"\texport PATH=%q\n",
fullname,
strings.Join(newpaths, ":"),
), nil
}
func isInPath(home, pathentry string) (int, bool) {
paths := Paths()
index := -1
for i := range paths {
@ -205,15 +262,9 @@ func ensureNotInPath(home, pathentry string) error {
}
}
if index >= 0 {
fmt.Fprintf(
os.Stderr,
"%q is in your PATH at position %d and must be removed manually to re-order\n",
pathentry,
index,
)
os.Exit(3)
return index, true
}
return nil
return -1, false
}
func normalizeEntryAndFile(home, pathentry string) (string, string, error) {
@ -321,59 +372,3 @@ func getOrder(nodes []os.FileInfo, pathentry, fname, envpathd string, fn sorter)
return priority, nil
}
func removePath(oldpathentry string) (string, error) {
// TODO Show current PATH sans this item
/*
oldpaths := paths
paths = []string{}
for i := range oldpaths {
if i != index {
paths = append(paths, oldpaths[i])
}
}
*/
home, err := os.UserHomeDir()
if nil != err {
return "", err
}
home = filepath.ToSlash(home)
pathentry, fname, err := normalizeEntryAndFile(home, oldpathentry)
if nil != err {
return "", err
}
envpathd := filepath.Join(home, ".config/envpath/path.d")
err = os.MkdirAll(envpathd, 0755)
if nil != err {
return "", err
}
/*
err = ensureNotInPath(home, pathentry)
if nil != err {
return "", err
}
*/
nodes, err := ioutil.ReadDir(envpathd)
if nil != err {
return "", err
}
// TODO rename getOrder to getNext
_, err = getOrder(nodes, pathentry, fname, envpathd, sortForward)
if nil == err {
fmt.Fprintf(os.Stderr, "%q is not managed by envpath.\n", pathentry)
}
/*
if index < 0 {
fmt.Fprintf(os.Stderr, "%q is NOT in PATH.\n", pathentry)
os.Exit(3)
}
*/
return "", nil
}