github.com/mattn/gom@v0.0.0-20190726063113-0ebf2b5d812d/gen.go (about)

     1  package main
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"go/build"
     7  	"os"
     8  	"path/filepath"
     9  	"sort"
    10  	"strings"
    11  )
    12  
    13  type importPackages []importPackage
    14  type importPackage struct {
    15  	path       string
    16  	isTestFile bool
    17  }
    18  
    19  func (slice importPackages) Len() int {
    20  	return len(slice)
    21  }
    22  
    23  func (slice importPackages) Less(i, j int) bool {
    24  	return slice[i].path < slice[j].path
    25  }
    26  
    27  func (slice importPackages) Swap(i, j int) {
    28  	slice[i], slice[j] = slice[j], slice[i]
    29  }
    30  
    31  const travis_yml = ".travis.yml"
    32  
    33  func genTravisYml() error {
    34  	_, err := os.Stat(travis_yml)
    35  	if err == nil {
    36  		return errors.New(".travis.yml already exists")
    37  	}
    38  	f, err := os.Create(travis_yml)
    39  	if err != nil {
    40  		return err
    41  	}
    42  	defer f.Close()
    43  	f.WriteString(`language: go
    44  go:
    45    - tip
    46  before_install:
    47    - go get github.com/mattn/gom
    48  script:
    49    - $HOME/gopath/bin/gom install
    50    - $HOME/gopath/bin/gom test
    51  `)
    52  	return nil
    53  }
    54  
    55  func appendPkg(pkgs []importPackage, pkg string) ([]importPackage, bool) {
    56  	for _, ele := range pkgs {
    57  		if ele.path == pkg {
    58  			return pkgs, false
    59  		}
    60  	}
    61  	return append(pkgs, importPackage{path: pkg}), true
    62  }
    63  
    64  func appendPkgs(pkgs, more []importPackage) []importPackage {
    65  	for _, pkg := range more {
    66  		pkgs, _ = appendPkg(pkgs, pkg.path)
    67  	}
    68  	return pkgs
    69  }
    70  
    71  func scanDirectory(path, srcDir string) (ret []importPackage, err error) {
    72  	pkg, err := build.Import(path, srcDir, build.AllowBinary)
    73  	if err != nil {
    74  		return ret, err
    75  	}
    76  	for _, imp := range pkg.Imports {
    77  		if imp == "C" {
    78  			continue
    79  		}
    80  		switch {
    81  		case pkg.Goroot:
    82  			// Ignore standard packages
    83  		case !build.IsLocalImport(imp):
    84  			// Add the external package
    85  			ret, _ = appendPkg(ret, imp)
    86  			fallthrough
    87  		default:
    88  			// Does the recursive walk
    89  			pkgs, err := scanDirectory(imp, pkg.Dir)
    90  			if err != nil {
    91  				return ret, err
    92  			}
    93  			ret = appendPkgs(ret, pkgs)
    94  		}
    95  	}
    96  	retTests := []importPackage{}
    97  	isAdd := false
    98  	for _, imp := range pkg.TestImports {
    99  		switch {
   100  		case pkg.Goroot:
   101  			// Ignore standard packages
   102  			break
   103  		case !build.IsLocalImport(imp):
   104  			// Add the external package
   105  			retTests, isAdd = appendPkg(retTests, imp)
   106  			if isAdd {
   107  				retTests[len(retTests)-1].isTestFile = true
   108  			}
   109  		}
   110  	}
   111  	ret = append(ret, retTests...)
   112  	return ret, err
   113  }
   114  
   115  func vcsScan(p, target string) (*vcsCmd, string, string) {
   116  	name := ""
   117  	for _, elem := range strings.Split(target, "/") {
   118  		var vcs *vcsCmd
   119  		p = filepath.Join(p, elem)
   120  		if name == "" {
   121  			name = elem
   122  		} else {
   123  			name += `/` + elem
   124  		}
   125  		if isDir(filepath.Join(p, ".git")) {
   126  			vcs = git
   127  		} else if isDir(filepath.Join(p, ".hg")) {
   128  			vcs = hg
   129  		} else if isDir(filepath.Join(p, ".bzr")) {
   130  			vcs = bzr
   131  		}
   132  		if vcs != nil {
   133  			return vcs, name, p
   134  		}
   135  	}
   136  	return nil, "", ""
   137  }
   138  
   139  func genGomfile() error {
   140  	_, err := os.Stat("Gomfile")
   141  	if err == nil {
   142  		return errors.New("Gomfile already exists")
   143  	}
   144  	dir, err := os.Getwd()
   145  	if err != nil {
   146  		return err
   147  	}
   148  	all, err := scanDirectory(".", dir)
   149  	if err != nil {
   150  		return err
   151  	}
   152  	sort.Sort(importPackages(all))
   153  	goms := make([]Gom, 0)
   154  	for _, pkg := range all {
   155  		for _, p := range filepath.SplitList(os.Getenv("GOPATH")) {
   156  			var vcs *vcsCmd
   157  			var n string
   158  			vcs, n, p = vcsScan(filepath.Join(p, "src"), pkg.path)
   159  			if vcs != nil {
   160  				found := false
   161  				for _, gom := range goms {
   162  					if gom.name == n {
   163  						found = true
   164  						break
   165  					}
   166  				}
   167  				if !found {
   168  					gom := Gom{name: n, options: make(map[string]interface{})}
   169  					rev, err := vcs.Revision(p)
   170  					if err == nil && rev != "" {
   171  						gom.options["commit"] = rev
   172  					}
   173  					if pkg.isTestFile {
   174  						gom.options["group"] = "test"
   175  					}
   176  					goms = append(goms, gom)
   177  				}
   178  			}
   179  		}
   180  	}
   181  
   182  	return writeGomfile("Gomfile", goms)
   183  }
   184  
   185  func genGomfileLock() error {
   186  	allGoms, err := parseGomfile("Gomfile")
   187  	if err != nil {
   188  		return err
   189  	}
   190  	vendor, err := filepath.Abs(vendorFolder)
   191  	if err != nil {
   192  		return err
   193  	}
   194  	goms := make([]Gom, 0)
   195  	for _, gom := range allGoms {
   196  		if group, ok := gom.options["group"]; ok {
   197  			if !matchEnv(group) {
   198  				continue
   199  			}
   200  		}
   201  		if goos, ok := gom.options["goos"]; ok {
   202  			if !matchOS(goos) {
   203  				continue
   204  			}
   205  		}
   206  		goms = append(goms, gom)
   207  	}
   208  
   209  	for _, gom := range goms {
   210  		var vcs *vcsCmd
   211  		var p string
   212  		vcs, _, p = vcsScan(vendorSrc(vendor), gom.name)
   213  		if vcs != nil {
   214  			rev, err := vcs.Revision(p)
   215  			if err == nil && rev != "" {
   216  				gom.options["commit"] = rev
   217  			}
   218  		}
   219  	}
   220  	err = writeGomfile("Gomfile.lock", goms)
   221  	if err == nil {
   222  		fmt.Println("Gomfile.lock is generated")
   223  	}
   224  	return err
   225  }