gopkg.in/tools/godep.v56@v56.0.0-20160226230103-b32db8cfcaad/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"io"
     7  	"log"
     8  	"os"
     9  	"path/filepath"
    10  	"runtime/pprof"
    11  	"strings"
    12  	"text/template"
    13  )
    14  
    15  var (
    16  	cpuprofile       string
    17  	verbose          bool // Verbose flag for commands that support it
    18  	debug            bool // Debug flag for commands that support it
    19  	majorGoVersion   string
    20  	VendorExperiment bool
    21  	sep              string
    22  )
    23  
    24  // Command is an implementation of a godep command
    25  // like godep save or godep go.
    26  type Command struct {
    27  	// Run runs the command.
    28  	// The args are the arguments after the command name.
    29  	Run func(cmd *Command, args []string)
    30  
    31  	// Name of the command
    32  	Name string
    33  
    34  	// Args the command would expect
    35  	Args string
    36  
    37  	// Short is the short description shown in the 'godep help' output.
    38  	Short string
    39  
    40  	// Long is the long message shown in the
    41  	// 'godep help <this-command>' output.
    42  	Long string
    43  
    44  	// Flag is a set of flags specific to this command.
    45  	Flag flag.FlagSet
    46  }
    47  
    48  // UsageExit prints usage information and exits.
    49  func (c *Command) UsageExit() {
    50  	fmt.Fprintf(os.Stderr, "Args: godep %s [-v] [-d] %s\n\n", c.Name, c.Args)
    51  	fmt.Fprintf(os.Stderr, "Run 'godep help %s' for help.\n", c.Name)
    52  	os.Exit(2)
    53  }
    54  
    55  // Commands lists the available commands and help topics.
    56  // The order here is the order in which they are printed
    57  // by 'godep help'.
    58  var commands = []*Command{
    59  	cmdSave,
    60  	cmdGo,
    61  	cmdGet,
    62  	cmdPath,
    63  	cmdRestore,
    64  	cmdUpdate,
    65  	cmdDiff,
    66  	cmdVersion,
    67  }
    68  
    69  // VendorExperiment is the Go 1.5 vendor directory experiment flag, see
    70  // https://github.com/golang/go/commit/183cc0cd41f06f83cb7a2490a499e3f9101befff
    71  // Honor the env var unless the project already has an old school godep workspace
    72  func determineVendor(v string) bool {
    73  	go15ve := os.Getenv("GO15VENDOREXPERIMENT")
    74  	ev := (v == "go1.5" && go15ve == "1") ||
    75  		(v == "go1.6" && go15ve != "0") ||
    76  		(v == "devel" && go15ve != "0")
    77  
    78  	ws := filepath.Join("Godeps", "_workspace")
    79  	s, err := os.Stat(ws)
    80  	if err == nil && s.IsDir() {
    81  		if ev {
    82  			log.Printf("WARNING: Go version (%s) & $GO15VENDOREXPERIMENT=%s wants to enable the vendor experiment, but disabling because a Godep workspace (%s) exists\n", v, go15ve, ws)
    83  		}
    84  		return false
    85  	}
    86  
    87  	return ev
    88  }
    89  
    90  func main() {
    91  	log.SetFlags(0)
    92  	log.SetPrefix("godep: ")
    93  	log.SetOutput(os.Stderr)
    94  
    95  	flag.Usage = usageExit
    96  	flag.Parse()
    97  	args := flag.Args()
    98  	if len(args) < 1 {
    99  		usageExit()
   100  	}
   101  
   102  	if args[0] == "help" {
   103  		help(args[1:])
   104  		return
   105  	}
   106  
   107  	var err error
   108  	majorGoVersion, err = goVersion()
   109  	if err != nil {
   110  		log.Fatal(err)
   111  	}
   112  
   113  	VendorExperiment = determineVendor(majorGoVersion)
   114  
   115  	// sep is the signature set of path elements that
   116  	// precede the original path of an imported package.
   117  	sep = defaultSep(VendorExperiment)
   118  
   119  	for _, cmd := range commands {
   120  		if cmd.Name == args[0] {
   121  			cmd.Flag.BoolVar(&verbose, "v", false, "enable verbose output")
   122  			cmd.Flag.BoolVar(&debug, "d", false, "enable debug output")
   123  			cmd.Flag.StringVar(&cpuprofile, "cpuprofile", "", "Write cpu profile to this file")
   124  			cmd.Flag.Usage = func() { cmd.UsageExit() }
   125  			cmd.Flag.Parse(args[1:])
   126  
   127  			debugln("versionString()", versionString())
   128  			debugln("majorGoVersion", majorGoVersion)
   129  			debugln("VendorExperiment", VendorExperiment)
   130  			debugln("sep", sep)
   131  
   132  			if cpuprofile != "" {
   133  				f, err := os.Create(cpuprofile)
   134  				if err != nil {
   135  					log.Fatal(err)
   136  				}
   137  				pprof.StartCPUProfile(f)
   138  				defer pprof.StopCPUProfile()
   139  			}
   140  			cmd.Run(cmd, cmd.Flag.Args())
   141  			return
   142  		}
   143  	}
   144  
   145  	fmt.Fprintf(os.Stderr, "godep: unknown command %q\n", args[0])
   146  	fmt.Fprintf(os.Stderr, "Run 'godep help' for usage.\n")
   147  	os.Exit(2)
   148  }
   149  
   150  var usageTemplate = `
   151  Godep is a tool for managing Go package dependencies.
   152  
   153  Usage:
   154  
   155  	godep command [arguments]
   156  
   157  The commands are:
   158  {{range .}}
   159      {{.Name | printf "%-8s"}} {{.Short}}{{end}}
   160  
   161  Use "godep help [command]" for more information about a command.
   162  `
   163  
   164  var helpTemplate = `
   165  Args: godep {{.Name}} [-v] [-d] {{.Args}}
   166  
   167  {{.Long | trim}}
   168  
   169  If -v is given, verbose output is enabled.
   170  
   171  If -d is given, debug output is enabled (you probably don't want this, see -v).
   172  
   173  `
   174  
   175  func help(args []string) {
   176  	if len(args) == 0 {
   177  		printUsage(os.Stdout)
   178  		return
   179  	}
   180  	if len(args) != 1 {
   181  		fmt.Fprintf(os.Stderr, "usage: godep help command\n\n")
   182  		fmt.Fprintf(os.Stderr, "Too many arguments given.\n")
   183  		os.Exit(2)
   184  	}
   185  	for _, cmd := range commands {
   186  		if cmd.Name == args[0] {
   187  			tmpl(os.Stdout, helpTemplate, cmd)
   188  			return
   189  		}
   190  	}
   191  }
   192  
   193  func usageExit() {
   194  	printUsage(os.Stderr)
   195  	os.Exit(2)
   196  }
   197  
   198  func printUsage(w io.Writer) {
   199  	tmpl(w, usageTemplate, commands)
   200  }
   201  
   202  // tmpl executes the given template text on data, writing the result to w.
   203  func tmpl(w io.Writer, text string, data interface{}) {
   204  	t := template.New("top")
   205  	t.Funcs(template.FuncMap{
   206  		"trim": strings.TrimSpace,
   207  	})
   208  	template.Must(t.Parse(strings.TrimSpace(text) + "\n\n"))
   209  	if err := t.Execute(w, data); err != nil {
   210  		panic(err)
   211  	}
   212  }