code.cestus.io/tools/fabricator@v0.4.3/pkg/cmd/plugin.go (about)

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  	"runtime"
    10  	"strings"
    11  
    12  	"code.cestus.io/tools/fabricator/pkg/fabricator"
    13  	"code.cestus.io/tools/fabricator/pkg/helpers"
    14  )
    15  
    16  // DefaultPluginHandler implements PluginHandler
    17  type DefaultPluginHandler struct {
    18  	ValidPrefixes []string
    19  	IO            fabricator.IOStreams
    20  }
    21  
    22  // NewDefaultPluginHandler instantiates the DefaultPluginHandler with a list of
    23  // given filename prefixes used to identify valid plugin filenames.
    24  func NewDefaultPluginHandler(validPrefixes []string, io fabricator.IOStreams) *DefaultPluginHandler {
    25  	return &DefaultPluginHandler{
    26  		ValidPrefixes: validPrefixes,
    27  		IO:            io,
    28  	}
    29  }
    30  
    31  func findExecutable(file string) error {
    32  	d, err := os.Stat(file)
    33  	if err != nil {
    34  		return err
    35  	}
    36  	if runtime.GOOS == "windows" {
    37  		fileExt := strings.ToLower(filepath.Ext(file))
    38  
    39  		switch fileExt {
    40  		case ".bat", ".cmd", ".com", ".exe", ".ps1":
    41  			return nil
    42  		}
    43  		return errors.New("not an executable")
    44  	}
    45  	if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
    46  		return nil
    47  	}
    48  	return errors.New("not an executable")
    49  }
    50  
    51  // Lookup implements PluginHandler
    52  func (h *DefaultPluginHandler) Lookup(ctx context.Context, filename string, paths []string) (string, bool) {
    53  	for _, prefix := range h.ValidPrefixes {
    54  		for _, dir := range paths {
    55  			if dir == "" {
    56  				// Unix shell semantics: path element "" means "."
    57  				dir = "."
    58  			}
    59  			path := filepath.Join(dir, fmt.Sprintf("%s-%s", prefix, filename))
    60  			if err := findExecutable(path); err == nil {
    61  				return path, true
    62  			}
    63  			if runtime.GOOS == "windows" {
    64  				ext := []string{".bat", ".cmd", ".com", ".exe", ".ps1"}
    65  				for _, e := range ext {
    66  					np := fmt.Sprintf("%s%s", path, e)
    67  					if err := findExecutable(np); err == nil {
    68  						return path, true
    69  					}
    70  				}
    71  			}
    72  		}
    73  	}
    74  	return "", false
    75  }
    76  
    77  // Execute implements PluginHandler
    78  func (h *DefaultPluginHandler) Execute(ctx context.Context, executablePath string, cmdArgs []string, environment fabricator.Environment) error {
    79  	executor := helpers.NewExecutor("", h.IO).WithEnvMap(environment)
    80  	err := executor.Run(ctx, executablePath, cmdArgs...)
    81  	return err
    82  }