From 4827ffbf03e316323ea06dea71f4a73f7dae6f92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Tue, 30 Jun 2020 13:47:15 +0200 Subject: [PATCH] Raise more informative path error when reading config file Example: remove or rename regular file `/home/foo/.config/gh` (must be a directory) --- internal/config/config_file.go | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/internal/config/config_file.go b/internal/config/config_file.go index 49a2770d3..d2ef9891b 100644 --- a/internal/config/config_file.go +++ b/internal/config/config_file.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "path" + "syscall" "github.com/mitchellh/go-homedir" "gopkg.in/yaml.v3" @@ -32,7 +33,7 @@ func ParseDefaultConfig() (Config, error) { var ReadConfigFile = func(filename string) ([]byte, error) { f, err := os.Open(filename) if err != nil { - return nil, err + return nil, pathError(err) } defer f.Close() @@ -47,7 +48,7 @@ var ReadConfigFile = func(filename string) ([]byte, error) { var WriteConfigFile = func(filename string, data []byte) error { err := os.MkdirAll(path.Dir(filename), 0771) if err != nil { - return err + return pathError(err) } cfgFile, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) // cargo coded from setup @@ -168,3 +169,28 @@ func ParseConfig(filename string) (Config, error) { return NewConfig(root), nil } + +func pathError(err error) error { + var pathError *os.PathError + if errors.As(err, &pathError) && errors.Is(pathError.Err, syscall.ENOTDIR) { + if p := findRegularFile(pathError.Path); p != "" { + return fmt.Errorf("remove or rename regular file `%s` (must be a directory)", p) + } + + } + return err +} + +func findRegularFile(p string) string { + for { + if s, err := os.Stat(p); err == nil && s.Mode().IsRegular() { + return p + } + newPath := path.Dir(p) + if newPath == p || newPath == "/" || newPath == "." { + break + } + p = newPath + } + return "" +}