diff options
author | Ollie Phillips <oliver@eantics.co.uk> | 2017-02-24 19:03:32 +0000 |
---|---|---|
committer | Ollie Phillips <oliver@eantics.co.uk> | 2017-02-24 19:03:32 +0000 |
commit | 2884d7d75e6a802f03d5af9c572b6aaf24e17d20 (patch) | |
tree | d26821fe76e253fb153e614e6caaf5af33e887f1 /cmd/ponzu/add.go | |
parent | 28c360a44d93e55aec2625fa83e62f2b2816d534 (diff) |
Implemented a replicateAll func, since we need files to remain in GOPATH/src
Diffstat (limited to 'cmd/ponzu/add.go')
-rw-r--r-- | cmd/ponzu/add.go | 133 |
1 files changed, 117 insertions, 16 deletions
diff --git a/cmd/ponzu/add.go b/cmd/ponzu/add.go index 0573a99..dd8af6c 100644 --- a/cmd/ponzu/add.go +++ b/cmd/ponzu/add.go @@ -2,14 +2,15 @@ package main import ( "errors" - "log" + "fmt" + "io" "os" "os/exec" "path/filepath" "strings" ) -// Use `go get` to download addon and add to $GOPATH/src, useful +// use `go get` to download addon and add to $GOPATH/src, useful // for IDE auto-import and code completion, then copy entire directory // tree to project's ./addons folder func getAddon(args []string) error { @@ -25,35 +26,32 @@ func getAddon(args []string) error { err := get.Start() if err != nil { - addError(err) + return addError(err) } err = get.Wait() if err != nil { - addError(err) + return addError(err) } - // Copy to ./addons folder + // copy to ./addons folder // GOPATH can be a list delimited by ":" on Linux or ";" on Windows // `go get` uses the first, this should parse out the first whatever the OS gopath := resolveGOPATH() pwd, err := os.Getwd() if err != nil { - addError(err) + return addError(err) } src := filepath.Join(gopath, "src", addonPath) - dest := filepath.Join(pwd, "addons", addonPath) - log.Println(dest) - err = os.Mkdir(dest, os.ModeDir|os.ModePerm) - if err != nil { - addError(err) - } - err = copyAll(src, dest) + // Need to strip the addon name for copyAll? + last := filepath.Base(addonPath) + dest := filepath.Join(pwd, "addons", strings.Replace(addonPath, last, "", 1)) + + err = replicateAll(src, dest) if err != nil { - log.Println(err) - //addError(err) + return addError(err) } return nil } @@ -70,7 +68,110 @@ func resolveGOPATH() string { return gopath } -// error return +// this is distinct from copyAll() in that files are copied, not moved, +// since we also need them to remain in $GOPATH/src +// thanks to @markc of stack overflow for the copyFile and copyFileContents functions +func replicateAll(src, dst string) error { + err := filepath.Walk(src, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + sep := string(filepath.Separator) + + // base == the ponzu project dir + string(filepath.Separator) + parts := strings.Split(src, sep) + base := strings.Join(parts[:len(parts)-1], sep) + base += sep + + target := filepath.Join(dst, path[len(base):]) + + // if its a directory, make dir in dst + if info.IsDir() { + err := os.MkdirAll(target, os.ModeDir|os.ModePerm) + if err != nil { + return err + } + } else { + // if its a file, copy file to dir of dst + err = copyFile(path, target) + if err != nil { + return err + } + } + + return nil + }) + if err != nil { + return err + } + + return nil +} + +// copyFile copies a file from src to dst. if src and dst files exist, and are +// the same, then return success. Otherise, attempt to create a hard link +// between the two files. If that fail, copy the file contents from src to dst. +// thanks to Stack Overflow +func copyFile(src, dst string) (err error) { + sfi, err := os.Stat(src) + if err != nil { + return + } + if !sfi.Mode().IsRegular() { + // cannot copy non-regular files (e.g., directories, + // symlinks, devices, etc.) + return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String()) + } + dfi, err := os.Stat(dst) + if err != nil { + if !os.IsNotExist(err) { + return + } + } else { + if !(dfi.Mode().IsRegular()) { + return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String()) + } + if os.SameFile(sfi, dfi) { + return + } + } + if err = os.Link(src, dst); err == nil { + return + } + err = copyFileContents(src, dst) + return +} + +// copyFileContents copies the contents of the file named src to the file named +// by dst. The file will be created if it does not already exist. If the +// destination file exists, all it's contents will be replaced by the contents +// of the source file. +// Thanks for Stack Overflow +func copyFileContents(src, dst string) (err error) { + in, err := os.Open(src) + if err != nil { + return + } + defer in.Close() + out, err := os.Create(dst) + if err != nil { + return + } + defer func() { + cerr := out.Close() + if err == nil { + err = cerr + } + }() + if _, err = io.Copy(out, in); err != nil { + return + } + err = out.Sync() + return +} + +// generic error return func addError(err error) error { return errors.New("Ponzu add failed. " + "\n" + err.Error()) } |