github.com/traefik/yaegi@v0.15.1/cmd/yaegi/extract.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"flag"
     7  	"fmt"
     8  	"io"
     9  	"os"
    10  	"path/filepath"
    11  	"strings"
    12  
    13  	"github.com/traefik/yaegi/extract"
    14  )
    15  
    16  func extractCmd(arg []string) error {
    17  	var licensePath string
    18  	var name string
    19  	var exclude string
    20  	var include string
    21  	var tag string
    22  
    23  	eflag := flag.NewFlagSet("run", flag.ContinueOnError)
    24  	eflag.StringVar(&licensePath, "license", "", "path to a LICENSE file")
    25  	eflag.StringVar(&name, "name", "", "the namespace for the extracted symbols")
    26  	eflag.StringVar(&exclude, "exclude", "", "comma separated list of regexp matching symbols to exclude")
    27  	eflag.StringVar(&include, "include", "", "comma separated list of regexp matching symbols to include")
    28  	eflag.StringVar(&tag, "tag", "", "comma separated list of build tags to be added to the created package")
    29  	eflag.Usage = func() {
    30  		fmt.Println("Usage: yaegi extract [options] packages...")
    31  		fmt.Println("Options:")
    32  		eflag.PrintDefaults()
    33  	}
    34  
    35  	if err := eflag.Parse(arg); err != nil {
    36  		return err
    37  	}
    38  
    39  	args := eflag.Args()
    40  	if len(args) == 0 {
    41  		return fmt.Errorf("missing package")
    42  	}
    43  
    44  	license, err := genLicense(licensePath)
    45  	if err != nil {
    46  		return err
    47  	}
    48  
    49  	wd, err := os.Getwd()
    50  	if err != nil {
    51  		return err
    52  	}
    53  
    54  	if name == "" {
    55  		name = filepath.Base(wd)
    56  	}
    57  	ext := extract.Extractor{
    58  		Dest:    name,
    59  		License: license,
    60  	}
    61  	if tag != "" {
    62  		ext.Tag = strings.Split(tag, ",")
    63  	}
    64  
    65  	if exclude != "" {
    66  		ext.Exclude = strings.Split(exclude, ",")
    67  	}
    68  	if include != "" {
    69  		ext.Include = strings.Split(include, ",")
    70  	}
    71  
    72  	r := strings.NewReplacer("/", "-", ".", "_")
    73  
    74  	for _, pkgIdent := range args {
    75  		var buf bytes.Buffer
    76  		importPath, err := ext.Extract(pkgIdent, name, &buf)
    77  		if err != nil {
    78  			fmt.Fprintln(os.Stderr, err)
    79  			continue
    80  		}
    81  
    82  		oFile := r.Replace(importPath) + ".go"
    83  		f, err := os.Create(oFile)
    84  		if err != nil {
    85  			return err
    86  		}
    87  
    88  		if _, err := io.Copy(f, &buf); err != nil {
    89  			_ = f.Close()
    90  			return err
    91  		}
    92  
    93  		if err := f.Close(); err != nil {
    94  			return err
    95  		}
    96  	}
    97  
    98  	return nil
    99  }
   100  
   101  // genLicense generates the correct LICENSE header text from the provided
   102  // path to a LICENSE file.
   103  func genLicense(fname string) (string, error) {
   104  	if fname == "" {
   105  		return "", nil
   106  	}
   107  
   108  	f, err := os.Open(fname)
   109  	if err != nil {
   110  		return "", fmt.Errorf("could not open LICENSE file: %w", err)
   111  	}
   112  	defer func() { _ = f.Close() }()
   113  
   114  	license := new(strings.Builder)
   115  	sc := bufio.NewScanner(f)
   116  	for sc.Scan() {
   117  		txt := sc.Text()
   118  		if txt != "" {
   119  			txt = " " + txt
   120  		}
   121  		license.WriteString("//" + txt + "\n")
   122  	}
   123  	if sc.Err() != nil {
   124  		return "", fmt.Errorf("could not scan LICENSE file: %w", err)
   125  	}
   126  
   127  	return license.String(), nil
   128  }