github.com/aca02djr/gb@v0.4.1/fileutils/fileutils.go (about)

     1  // package fileutils provides utililty methods to copy and move files and directories.
     2  package fileutils
     3  
     4  import (
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"path/filepath"
     9  	"runtime"
    10  	"strings"
    11  )
    12  
    13  const debugCopypath = false
    14  const debugCopyfile = false
    15  
    16  // Copypath copies the contents of src to dst, excluding any file or
    17  // directory that starts with a period.
    18  func Copypath(dst string, src string) error {
    19  	err := filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
    20  		if err != nil {
    21  			return err
    22  		}
    23  
    24  		if strings.HasPrefix(filepath.Base(path), ".") {
    25  			if info.IsDir() {
    26  				return filepath.SkipDir
    27  			}
    28  			return nil
    29  		}
    30  
    31  		if info.IsDir() {
    32  			return nil
    33  		}
    34  
    35  		if info.Mode()&os.ModeSymlink != 0 {
    36  			if debugCopypath {
    37  				fmt.Printf("skipping symlink: %v\n", path)
    38  			}
    39  			return nil
    40  		}
    41  
    42  		dst := filepath.Join(dst, path[len(src):])
    43  		return Copyfile(dst, path)
    44  	})
    45  	if err != nil {
    46  		// if there was an error during copying, remove the partial copy.
    47  		RemoveAll(dst)
    48  	}
    49  	return err
    50  }
    51  
    52  func Copyfile(dst, src string) error {
    53  	err := mkdir(filepath.Dir(dst))
    54  	if err != nil {
    55  		return fmt.Errorf("copyfile: mkdirall: %v", err)
    56  	}
    57  	r, err := os.Open(src)
    58  	if err != nil {
    59  		return fmt.Errorf("copyfile: open(%q): %v", src, err)
    60  	}
    61  	defer r.Close()
    62  	w, err := os.Create(dst)
    63  	if err != nil {
    64  		return fmt.Errorf("copyfile: create(%q): %v", dst, err)
    65  	}
    66  	defer w.Close()
    67  	if debugCopyfile {
    68  		fmt.Printf("copyfile(dst: %v, src: %v)\n", dst, src)
    69  	}
    70  	_, err = io.Copy(w, r)
    71  	return err
    72  }
    73  
    74  // RemoveAll removes path and any children it contains. Unlike os.RemoveAll it
    75  // deletes read only files on Windows.
    76  func RemoveAll(path string) error {
    77  	if runtime.GOOS == "windows" {
    78  		// Simple case: if Remove works, we're done.
    79  		err := os.Remove(path)
    80  		if err == nil || os.IsNotExist(err) {
    81  			return nil
    82  		}
    83  		// make sure all files are writable so we can delete them
    84  		filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
    85  			if err != nil {
    86  				// walk gave us some error, give it back.
    87  				return err
    88  			}
    89  			mode := info.Mode()
    90  			if mode|0200 == mode {
    91  				return nil
    92  			}
    93  			return os.Chmod(path, mode|0200)
    94  		})
    95  	}
    96  	return os.RemoveAll(path)
    97  }
    98  
    99  func mkdir(path string) error {
   100  	return os.MkdirAll(path, 0755)
   101  }