github.com/ahmet2mir/goreleaser@v0.180.3-0.20210927151101-8e5ee5a9b8c5/internal/gio/copy.go (about)

     1  package gio
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/apex/log"
    11  )
    12  
    13  // Copy recursively copies src into dst with src's file modes.
    14  func Copy(src, dst string) error {
    15  	return CopyWithMode(src, dst, 0)
    16  }
    17  
    18  // CopyWithMode recursively copies src into dst with the given mode.
    19  // The given mode applies only to files. Their parent dirs will have the same mode as their src counterparts.
    20  func CopyWithMode(src, dst string, mode os.FileMode) error {
    21  	return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
    22  		if err != nil {
    23  			return fmt.Errorf("failed to copy %s to %s: %w", src, dst, err)
    24  		}
    25  		// We have the following:
    26  		// - src = "a/b"
    27  		// - dst = "dist/linuxamd64/b"
    28  		// - path = "a/b/c.txt"
    29  		// So we join "a/b" with "c.txt" and use it as the destination.
    30  		dst := filepath.Join(dst, strings.Replace(path, src, "", 1))
    31  		log.WithFields(log.Fields{
    32  			"src": path,
    33  			"dst": dst,
    34  		}).Debug("copying file")
    35  		if info.IsDir() {
    36  			return os.MkdirAll(dst, info.Mode())
    37  		}
    38  		if mode != 0 {
    39  			return copyFile(path, dst, mode)
    40  		}
    41  		return copyFile(path, dst, info.Mode())
    42  	})
    43  }
    44  
    45  func copyFile(src, dst string, mode os.FileMode) error {
    46  	original, err := os.Open(src)
    47  	if err != nil {
    48  		return fmt.Errorf("failed to open '%s': %w", src, err)
    49  	}
    50  	defer original.Close()
    51  
    52  	new, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode)
    53  	if err != nil {
    54  		return fmt.Errorf("failed to open '%s': %w", dst, err)
    55  	}
    56  	defer new.Close()
    57  
    58  	if _, err := io.Copy(new, original); err != nil {
    59  		return fmt.Errorf("failed to copy: %w", err)
    60  	}
    61  	return nil
    62  }