diff --git a/config/user.go b/config/user.go index b39a4f5..f1a5e9a 100644 --- a/config/user.go +++ b/config/user.go @@ -1,127 +1,162 @@ package config import ( "encoding/json" "io/ioutil" "path/filepath" writeas "github.com/writeas/go-writeas/v2" "github.com/writeas/writeas-cli/fileutils" "gopkg.in/urfave/cli.v1" ) func LoadUser(c *cli.Context) (*writeas.AuthUser, error) { dir, err := userHostDir(c) if err != nil { return nil, err } DirMustExist(dir) username, err := CurrentUser(c) if err != nil { return nil, err } if username == "user" { username = "" } fname := filepath.Join(dir, username, "user.json") userJSON, err := ioutil.ReadFile(fname) if err != nil { if !fileutils.Exists(fname) { // Don't return a file-not-found error return nil, nil } return nil, err } // Parse JSON file u := &writeas.AuthUser{} err = json.Unmarshal(userJSON, u) if err != nil { return nil, err } return u, nil } func DeleteUser(c *cli.Context) error { dir, err := userHostDir(c) if err != nil { return err } username, err := CurrentUser(c) if err != nil { return err } if username == "user" { username = "" } - return fileutils.DeleteFile(filepath.Join(dir, username, "user.json")) + // Delete user data + err = fileutils.DeleteFile(filepath.Join(dir, username, "user.json")) + if err != nil { + return err + } + + // Do additional cleanup in wf-cli + if c.App.Name == "wf" { + // Delete user dir if it's empty + userEmpty, err := fileutils.IsEmpty(filepath.Join(dir, username)) + if err != nil { + return err + } + if !userEmpty { + return nil + } + err = fileutils.DeleteFile(filepath.Join(dir, username)) + if err != nil { + return err + } + + // Delete host dir if it's empty + hostEmpty, err := fileutils.IsEmpty(dir) + if err != nil { + return err + } + if !hostEmpty { + return nil + } + err = fileutils.DeleteFile(dir) + if err != nil { + return err + } + } + + return nil } func SaveUser(c *cli.Context, u *writeas.AuthUser) error { // Marshal struct into pretty-printed JSON userJSON, err := json.MarshalIndent(u, "", " ") if err != nil { return err } dir, err := userHostDir(c) if err != nil { return err } // Save file username, err := CurrentUser(c) if err != nil { return err } if username != "user" { dir = filepath.Join(dir, u.User.Username) } DirMustExist(dir) err = ioutil.WriteFile(filepath.Join(dir, "user.json"), userJSON, 0600) if err != nil { return err } return nil } // userHostDir returns the path to the user data directory with the host based // subpath if the host flag is set func userHostDir(c *cli.Context) (string, error) { dataDir := UserDataDir(c.App.ExtraInfo()["configDir"]) hostDir, err := HostDirectory(c) if err != nil { return "", err } return filepath.Join(dataDir, hostDir), nil } // CurrentUser returns the username of the user taking action in the current // cli.Context. func CurrentUser(c *cli.Context) (string, error) { // Load host-level config, if host flag is set hostDir, err := userHostDir(c) if err != nil { return "", err } cfg, err := LoadConfig(hostDir) if err != nil { return "", err } if cfg.Default.User == "" { // Load app-level config cfg, err = LoadConfig(UserDataDir(c.App.ExtraInfo()["configDir"])) if err != nil { return "", err } } // Use user flag value if c.GlobalString("user") != "" { return c.GlobalString("user"), nil } return cfg.Default.User, nil } diff --git a/fileutils/fileutils.go b/fileutils/fileutils.go index 7e4c354..eda996b 100644 --- a/fileutils/fileutils.go +++ b/fileutils/fileutils.go @@ -1,111 +1,127 @@ package fileutils import ( "bufio" "fmt" + "io" "os" "strings" ) // Exists returns whether or not the given file exists func Exists(p string) bool { if _, err := os.Stat(p); !os.IsNotExist(err) { return true } return false } // WriteData writes data to the given path, creating the file if necessary. func WriteData(path string, data []byte) { f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) if err != nil { fmt.Println(err) } // TODO: check for Close() errors // https://github.com/ncw/swift/blob/master/swift.go#L170 defer f.Close() _, err = f.Write(data) if err != nil { fmt.Println(err) } } // ReadData returns file data as an array of lines from the file. func ReadData(p string) *[]string { f, err := os.Open(p) if err != nil { return nil } defer f.Close() lines := []string{} scanner := bufio.NewScanner(f) for scanner.Scan() { lines = append(lines, scanner.Text()) } if err := scanner.Err(); err != nil { return nil } return &lines } // RemoveLine searches for the line that starts with the given value and, // if found, removes it and saves the updated file. func RemoveLine(p, startsWith string) { f, err := os.Open(p) if err != nil { return } defer f.Close() var outText string found := false scanner := bufio.NewScanner(f) for scanner.Scan() { if strings.HasPrefix(scanner.Text(), startsWith) { found = true } else { outText += scanner.Text() + string('\n') } } if err := scanner.Err(); err != nil { return } if found { WriteData(p, []byte(outText)) } } // FindLine searches the given file for a line that begins with the given // string. func FindLine(p, startsWith string) string { f, err := os.Open(p) if err != nil { return "" } defer f.Close() scanner := bufio.NewScanner(f) for scanner.Scan() { if strings.HasPrefix(scanner.Text(), startsWith) { return scanner.Text() } } if err := scanner.Err(); err != nil { return "" } return "" } func DeleteFile(p string) error { return os.Remove(p) } + +// IsEmpty returns whether or not the given directory is empty +func IsEmpty(d string) (bool, error) { + f, err := os.Open(d) + if err != nil { + return false, err + } + defer f.Close() + + _, err = f.Readdirnames(1) + if err == io.EOF { + return true, nil + } + return false, err +}