From 9f4d2ac81b3d13c677605fa13ebc621ead9285bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mickae=CC=88l=20Menu?= Date: Fri, 25 Dec 2020 12:14:01 +0100 Subject: [PATCH] Refactor init command and add errors util --- .gitignore | 2 + cmd/init.go | 54 +------------------------ cmd/new.go | 11 ++++++ core/zk/zk.go | 92 +++++++++++++++++++++++++++++++++++++++++++ main.go | 1 + util/errors/errors.go | 18 +++++++++ 6 files changed, 126 insertions(+), 52 deletions(-) create mode 100644 cmd/new.go create mode 100644 core/zk/zk.go create mode 100644 util/errors/errors.go diff --git a/.gitignore b/.gitignore index 66fd13c..b4afdb2 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ # Dependency directories (remove the comment below to include it) # vendor/ + +.zk diff --git a/cmd/init.go b/cmd/init.go index 3ac40b4..f800519 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -1,61 +1,11 @@ package cmd -import ( - "errors" - "fmt" - "os" - "path/filepath" -) +import "github.com/mickael-menu/zk/core/zk" type Init struct { Directory string `arg optional name:"directory" default:"."` } func (cmd *Init) Run() error { - path, err := filepath.Abs(cmd.Directory) - if err != nil { - return err - } - - if existingPath, err := locateZk(path); err == nil { - return fmt.Errorf("a slip box already exists in %v", existingPath) - } - - // Create .zk and .zk/templates directories. - err = os.MkdirAll(filepath.Join(path, ".zk/templates"), os.ModePerm) - if err != nil { - return err - } - - return nil -} - -var ErrNotFound = errors.New("slip box not found") - -// locate finds the root of the slip box containing the given path. -func locateZk(path string) (string, error) { - if path == "/" || path == "." { - return "", ErrNotFound - } - if !filepath.IsAbs(path) { - panic("locateZk expects an absolute path") - } - if dotPath := filepath.Join(path, ".zk"); dirExists(dotPath) { - return path, nil - } - - return locateZk(filepath.Dir(path)) -} - -func dirExists(path string) bool { - fi, err := os.Stat(path) - if err != nil { - return false - } - switch mode := fi.Mode(); { - case mode.IsDir(): - return true - default: - return false - } + return zk.Create(cmd.Directory) } diff --git a/cmd/new.go b/cmd/new.go new file mode 100644 index 0000000..313176c --- /dev/null +++ b/cmd/new.go @@ -0,0 +1,11 @@ +package cmd + +import "github.com/mickael-menu/zk/core/zk" + +type New struct { + Directory string `arg optional name:"directory" default:"."` +} + +func (cmd *New) Run() error { + return zk.Open(cmd.Directory) +} diff --git a/core/zk/zk.go b/core/zk/zk.go new file mode 100644 index 0000000..7cd687e --- /dev/null +++ b/core/zk/zk.go @@ -0,0 +1,92 @@ +package zk + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/mickael-menu/zk/util/errors" +) + +const defaultConfig = ` +# Test +test = thing +` + +// Open locates a slip box at the given path and parses its configuration. +func Open(path string) error { + wrap := errors.Wrapper("open failed") + + path, err := filepath.Abs(path) + if err != nil { + return wrap(err) + } + _, err = locateRoot(path) + return wrap(err) +} + +// Create initializes a new slip box at the given path. +func Create(path string) error { + wrap := errors.Wrapper("init failed") + + path, err := filepath.Abs(path) + if err != nil { + return wrap(err) + } + + if existingPath, err := locateRoot(path); err == nil { + return wrap(fmt.Errorf("a slip box already exists in %v", existingPath)) + } + + // Create .zk and .zk/templates directories. + err = os.MkdirAll(filepath.Join(path, ".zk/templates"), os.ModePerm) + if err != nil { + return wrap(err) + } + + // Write default config.toml. + f, err := os.Create(filepath.Join(path, ".zk/config.toml")) + if err != nil { + return wrap(err) + } + _, err = f.WriteString(defaultConfig) + if err != nil { + return wrap(err) + } + + return nil +} + +// locate finds the root of the slip box containing the given path. +func locateRoot(path string) (string, error) { + if !filepath.IsAbs(path) { + panic("absolute path expected") + } + + var locate func(string) (string, error) + locate = func(currentPath string) (string, error) { + if currentPath == "/" || currentPath == "." { + return "", fmt.Errorf("no slip box found in %v or a parent directory", path) + } + if dotPath := filepath.Join(currentPath, ".zk"); dirExists(dotPath) { + return currentPath, nil + } + + return locate(filepath.Dir(currentPath)) + } + + return locate(path) +} + +func dirExists(path string) bool { + fi, err := os.Stat(path) + if err != nil { + return false + } + switch mode := fi.Mode(); { + case mode.IsDir(): + return true + default: + return false + } +} diff --git a/main.go b/main.go index e3987c7..ca297ce 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( var cli struct { Init cmd.Init `cmd help:"Create a slip box in the given directory"` + New cmd.New `cmd help:"Add a new note to the slip box"` } func main() { diff --git a/util/errors/errors.go b/util/errors/errors.go new file mode 100644 index 0000000..55b4f34 --- /dev/null +++ b/util/errors/errors.go @@ -0,0 +1,18 @@ +package errors + +import ( + "fmt" +) + +func Wrapper(msg string) func(error) error { + return func(err error) error { + return Wrap(err, msg) + } +} + +func Wrap(err error, msg string) error { + if err == nil { + return nil + } + return fmt.Errorf("%s: %w", msg, err) +}