scaffold/internal/template/copy.go

171 lines
3.0 KiB
Go

package template
import (
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"text/template"
"gitlab.com/wpetit/scaffold/internal/fs"
"gopkg.in/src-d/go-billy.v4"
"github.com/Masterminds/sprig"
"github.com/pkg/errors"
)
func CopyDir(vfs billy.Filesystem, baseDir string, dst string, opts *Option) error {
if opts == nil {
opts = &Option{}
}
baseDir = filepath.Clean(baseDir)
dst = filepath.Clean(dst)
_, err := os.Stat(dst)
if err != nil && !os.IsNotExist(err) {
return err
}
if err := os.MkdirAll(dst, 0755); err != nil {
return errors.Wrapf(err, "could not create directory '%s'", dst)
}
err = fs.Walk(vfs, baseDir, func(srcPath string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if srcPath == baseDir {
return nil
}
for _, p := range opts.IgnorePatterns {
match, err := filepath.Match(p, srcPath)
if err != nil {
return errors.Wrap(err, "could not match ignored file")
}
if match {
log.Printf("Ignoring %s.", srcPath)
return nil
}
}
relSrcPath, err := filepath.Rel(baseDir, srcPath)
if err != nil {
return err
}
dstPath := filepath.Join(dst, relSrcPath)
log.Printf("relSrcPath: %s, dstPath: %s", relSrcPath, dstPath)
if info.IsDir() {
log.Printf("creating dir '%s'", dstPath)
if err := os.MkdirAll(dstPath, 0755); err != nil {
return errors.Wrapf(err, "could not create directory '%s'", dstPath)
}
return nil
}
err = CopyFile(vfs, srcPath, dstPath, opts)
if err != nil {
return errors.Wrapf(err, "could not copy file '%s'", srcPath)
}
return nil
})
if err != nil {
return errors.Wrapf(err, "could not walk source directory '%s'", baseDir)
}
return nil
}
func CopyFile(vfs billy.Filesystem, src, dst string, opts *Option) (err error) {
if opts == nil {
opts = &Option{}
}
if !strings.HasSuffix(src, opts.TemplateExt) {
return copyFile(vfs, src, dst)
}
in, err := vfs.Open(src)
if err != nil {
return err
}
defer in.Close()
templateData, err := ioutil.ReadAll(in)
if err != nil {
return err
}
tmpl, err := template.New(filepath.Base(src)).Funcs(sprig.TxtFuncMap()).Parse(string(templateData))
if err != nil {
return err
}
dst = strings.TrimSuffix(dst, opts.TemplateExt)
log.Printf("templating file from '%s' to '%s'", src, dst)
out, err := os.Create(dst)
if err != nil {
return err
}
defer func() {
if e := out.Close(); e != nil {
err = e
}
}()
opts.TemplateData["SourceFile"] = src
opts.TemplateData["DestFile"] = dst
if err := tmpl.Execute(out, opts.TemplateData); err != nil {
return err
}
return nil
}
func copyFile(vfs billy.Filesystem, src, dst string) (err error) {
log.Printf("copying file '%s' to '%s'", src, dst)
in, err := vfs.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer func() {
if e := out.Close(); e != nil {
err = e
}
}()
_, err = io.Copy(out, in)
if err != nil {
return err
}
err = out.Sync()
if err != nil {
return err
}
return nil
}