github.com/kolbycrouch/elvish@v0.14.1-0.20210614162631-215b9ac1c423/pkg/shell/paths.go (about) 1 package shell 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "path/filepath" 8 9 "src.elv.sh/pkg/fsutil" 10 ) 11 12 // Paths keeps all paths required for the Elvish runtime. 13 type Paths struct { 14 RunDir string 15 Sock string 16 17 DataDir string 18 Db string 19 Rc string 20 LibDir string 21 22 Bin string 23 } 24 25 // MakePaths makes a populated Paths, using the given overrides. 26 func MakePaths(stderr io.Writer, overrides Paths) Paths { 27 p := overrides 28 setDir(&p.RunDir, "secure run directory", getSecureRunDir, stderr) 29 if p.RunDir != "" { 30 setChild(&p.Sock, p.RunDir, "sock") 31 } 32 33 setDir(&p.DataDir, "data directory", ensureDataDir, stderr) 34 if p.DataDir != "" { 35 setChild(&p.Db, p.DataDir, "db") 36 setChild(&p.Rc, p.DataDir, "rc.elv") 37 setChild(&p.LibDir, p.DataDir, "lib") 38 } 39 40 if p.Bin == "" { 41 binFile, err := os.Executable() 42 if err == nil { 43 p.Bin = binFile 44 } else { 45 fmt.Fprintln(stderr, "warning: cannot get executable path:", err) 46 } 47 } 48 return p 49 } 50 51 func setDir(p *string, what string, f func() (string, error), stderr io.Writer) { 52 if *p == "" { 53 dir, err := f() 54 if err == nil { 55 *p = dir 56 } else { 57 fmt.Fprintf(stderr, "warning: cannot create %v: %v\n", what, err) 58 } 59 } 60 } 61 62 func setChild(p *string, d, name string) { 63 if *p == "" { 64 *p = filepath.Join(d, name) 65 } 66 } 67 68 // Ensures Elvish's data directory exists, creating it if necessary. It returns 69 // the path to the data directory (never with a trailing slash) and possible 70 // error. 71 func ensureDataDir() (string, error) { 72 home, err := fsutil.GetHome("") 73 if err != nil { 74 return "", err 75 } 76 ddir := home + "/.elvish" 77 return ddir, os.MkdirAll(ddir, 0700) 78 }