Add basic interactive overwrite strategy

Available options:

- Do not copy
- Overwrite dest
- Copy source as dest.dist
This commit is contained in:
2020-05-23 11:56:44 +02:00
parent 7b694845f4
commit 3563860ede
9 changed files with 154 additions and 20 deletions

View File

@ -1,9 +1,9 @@
package template
import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
@ -13,6 +13,7 @@ import (
"gopkg.in/src-d/go-billy.v4"
"github.com/Masterminds/sprig"
"github.com/mattn/go-zglob"
"github.com/pkg/errors"
)
@ -43,12 +44,12 @@ func CopyDir(vfs billy.Filesystem, baseDir string, dst string, opts *Option) err
}
for _, p := range opts.IgnorePatterns {
match, err := filepath.Match(p, srcPath)
match, err := zglob.Match(p, strings.TrimPrefix(srcPath, "./"))
if err != nil {
return errors.Wrap(err, "could not match ignored file")
}
if match {
log.Printf("Ignoring %s.", srcPath)
fmt.Printf("Ignoring %s.\n", srcPath)
return nil
}
}
@ -61,7 +62,7 @@ func CopyDir(vfs billy.Filesystem, baseDir string, dst string, opts *Option) err
dstPath := filepath.Join(dst, relSrcPath)
if info.IsDir() {
log.Printf("creating dir '%s'", dstPath)
fmt.Printf("Creating dir '%s'.\n", dstPath)
if err := os.MkdirAll(dstPath, 0755); err != nil {
return errors.Wrapf(err, "could not create directory '%s'", dstPath)
}
@ -89,6 +90,44 @@ func CopyFile(vfs billy.Filesystem, src, dst string, opts *Option) (err error) {
opts = &Option{}
}
stat, err := os.Stat(dst)
if err != nil && !os.IsNotExist(err) {
return err
}
// If dst exists
if stat != nil {
strategy := opts.PreferredStrategy
if opts.Unnattended && opts.PreferredStrategy == -1 {
strategy = defaultStrategy
}
if opts.PreferredStrategy == -1 {
var useAsPreferredStrategy bool
strategy, useAsPreferredStrategy, err = askOverwriteStrategy(dst)
if err != nil {
return errors.Wrap(err, "could not ask for overwrite strategy")
}
if useAsPreferredStrategy {
opts.PreferredStrategy = strategy
}
}
switch strategy {
case CopyAsDist:
fmt.Printf("Using '%s.dist' as destination file.\n", dst)
dst += ".dist"
case DoNotCopy:
fmt.Printf("Skipping existing file '%s'.\n", dst)
return nil
default:
return nil
}
}
if !strings.HasSuffix(src, opts.TemplateExt) {
return copyFile(vfs, src, dst)
}
@ -111,7 +150,7 @@ func CopyFile(vfs billy.Filesystem, src, dst string, opts *Option) (err error) {
dst = strings.TrimSuffix(dst, opts.TemplateExt)
log.Printf("templating file from '%s' to '%s'", src, dst)
fmt.Printf("Templating file from '%s' to '%s'.\n", src, dst)
out, err := os.Create(dst)
if err != nil {
@ -135,7 +174,7 @@ func CopyFile(vfs billy.Filesystem, src, dst string, opts *Option) (err error) {
}
func copyFile(vfs billy.Filesystem, src, dst string) (err error) {
log.Printf("copying file '%s' to '%s'", src, dst)
fmt.Printf("Copying file '%s' to '%s'.\n", src, dst)
in, err := vfs.Open(src)
if err != nil {

View File

@ -0,0 +1,7 @@
package template
import "github.com/pkg/errors"
var (
ErrUnexpectedOverwriteStrategy = errors.New("unexpected overwrite strategy")
)

View File

@ -1,7 +1,9 @@
package template
type Option struct {
IgnorePatterns []string
TemplateData Data
TemplateExt string
IgnorePatterns []string
TemplateData Data
TemplateExt string
Unnattended bool
PreferredStrategy Strategy
}

View File

@ -0,0 +1,62 @@
package template
import (
"fmt"
"github.com/manifoldco/promptui"
"github.com/pkg/errors"
)
type Strategy int
const (
Undefined Strategy = -1
Overwrite Strategy = iota
CopyAsDist
DoNotCopy
)
// nolint: gochecknoglobals
var defaultStrategy = CopyAsDist
func askOverwriteStrategy(dst string) (Strategy, bool, error) {
strategyPrompt := promptui.Select{
Label: fmt.Sprintf("The file '%s' already exists. What do you want to do ?", dst),
Items: []string{
"Leave <dest> file as is",
"Copy source file as '<dest>.dist'",
"Overwrite '<dest>' with source file",
},
}
strategySelectedIndex, _, err := strategyPrompt.Run()
if err != nil {
return -1, false, errors.Wrap(err, "could not prompt for overwrite strategy")
}
asPreferredStrategyPrompt := promptui.Select{
Label: "Do you want to apply this strategy to all files ?",
Items: []string{
"Yes",
"No",
},
}
preferredSelectedIndex, _, err := asPreferredStrategyPrompt.Run()
if err != nil {
return -1, false, errors.Wrap(err, "could not prompt for preferred strategy")
}
useAsPreferredStrategy := preferredSelectedIndex == 0
switch strategySelectedIndex {
case 0:
return DoNotCopy, useAsPreferredStrategy, nil
case 1:
return CopyAsDist, useAsPreferredStrategy, nil
case 2:
return Overwrite, useAsPreferredStrategy, nil
default:
return -1, false, ErrUnexpectedOverwriteStrategy
}
}