From a7d30dd1d543a3c4ab6eefef6bb73ed96292a25a Mon Sep 17 00:00:00 2001 From: john Date: Tue, 9 Jul 2019 11:02:33 +0800 Subject: [PATCH] improve gfile --- g/os/gfile/gfile.go | 213 ++++++++++++++++++++------------------------ go.mod | 1 - 2 files changed, 95 insertions(+), 119 deletions(-) diff --git a/g/os/gfile/gfile.go b/g/os/gfile/gfile.go index 22cda24e2..717ffae7e 100644 --- a/g/os/gfile/gfile.go +++ b/g/os/gfile/gfile.go @@ -144,29 +144,109 @@ func Rename(src string, dst string) error { return Move(src, dst) } -// Copy file from to . +// Copy file/directory from to . // -// @TODO directory copy support. +// If is file, it calls CopyFile to implements copy feature, +// or else it calls CopyDir. func Copy(src string, dst string) error { - srcFile, err := Open(src) + if IsFile(src) { + return CopyFile(src, dst) + } + return CopyDir(src, dst) +} + +// CopyFile 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. The file mode will be copied from the source and +// the copied data is synced/flushed to stable storage. +// Thanks: https://gist.github.com/r0l1/92462b38df26839a3ca324697c8cba04 +func CopyFile(src, dst string) (err error) { + in, err := os.Open(src) + if err != nil { + return + } + defer func() { + if e := in.Close(); e != nil { + err = e + } + }() + out, err := os.Create(dst) + if err != nil { + return + } + defer func() { + if e := out.Close(); e != nil { + err = e + } + }() + _, err = io.Copy(out, in) + if err != nil { + return + } + err = out.Sync() + if err != nil { + return + } + si, err := os.Stat(src) + if err != nil { + return + } + err = os.Chmod(dst, si.Mode()) + if err != nil { + return + } + return +} + +// CopyDir recursively copies a directory tree, attempting to preserve permissions. +// Source directory must exist, destination directory must *not* exist. +// Symlinks are ignored and skipped. +func CopyDir(src string, dst string) (err error) { + src = filepath.Clean(src) + dst = filepath.Clean(dst) + si, err := os.Stat(src) if err != nil { return err } - defer srcFile.Close() - dstFile, err := Create(dst) - if err != nil { - return err + if !si.IsDir() { + return fmt.Errorf("source is not a directory") } - defer dstFile.Close() - _, err = io.Copy(dstFile, srcFile) - if err != nil { - return err + _, err = os.Stat(dst) + if err != nil && !os.IsNotExist(err) { + return } - err = dstFile.Sync() - if err != nil { - return err + if err == nil { + return fmt.Errorf("destination already exists") } - return nil + err = os.MkdirAll(dst, si.Mode()) + if err != nil { + return + } + entries, err := ioutil.ReadDir(src) + if err != nil { + return + } + for _, entry := range entries { + srcPath := filepath.Join(src, entry.Name()) + dstPath := filepath.Join(dst, entry.Name()) + if entry.IsDir() { + err = CopyDir(srcPath, dstPath) + if err != nil { + return + } + } else { + // Skip symlinks. + if entry.Mode()&os.ModeSymlink != 0 { + continue + } + err = CopyFile(srcPath, dstPath) + if err != nil { + return + } + } + } + return } // DirNames returns sub-file names of given directory . @@ -452,106 +532,3 @@ func MainPkgPath() string { func TempDir() string { return os.TempDir() } - -// https://gist.github.com/r0l1/92462b38df26839a3ca324697c8cba04 -// CopyFile 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. The file mode will be copied from the source and -// the copied data is synced/flushed to stable storage. -func CopyFile(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() { - if e := out.Close(); e != nil { - err = e - } - }() - - _, err = io.Copy(out, in) - if err != nil { - return - } - - err = out.Sync() - if err != nil { - return - } - - si, err := os.Stat(src) - if err != nil { - return - } - err = os.Chmod(dst, si.Mode()) - if err != nil { - return - } - - return -} - -// CopyDir recursively copies a directory tree, attempting to preserve permissions. -// Source directory must exist, destination directory must *not* exist. -// Symlinks are ignored and skipped. -func CopyDir(src string, dst string) (err error) { - src = filepath.Clean(src) - dst = filepath.Clean(dst) - - si, err := os.Stat(src) - if err != nil { - return err - } - if !si.IsDir() { - return fmt.Errorf("source is not a directory") - } - - _, err = os.Stat(dst) - if err != nil && !os.IsNotExist(err) { - return - } - if err == nil { - return fmt.Errorf("destination already exists") - } - - err = os.MkdirAll(dst, si.Mode()) - if err != nil { - return - } - - entries, err := ioutil.ReadDir(src) - if err != nil { - return - } - - for _, entry := range entries { - srcPath := filepath.Join(src, entry.Name()) - dstPath := filepath.Join(dst, entry.Name()) - - if entry.IsDir() { - err = CopyDir(srcPath, dstPath) - if err != nil { - return - } - } else { - // Skip symlinks. - if entry.Mode()&os.ModeSymlink != 0 { - continue - } - - err = CopyFile(srcPath, dstPath) - if err != nil { - return - } - } - } - - return -} diff --git a/go.mod b/go.mod index 081d99cd0..28729e4f6 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,2 @@ module github.com/gogf/gf -go 1.12