github.com/april1989/origin-go-tools@v0.0.32/cmd/getgo/main.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build !plan9 6 7 // The getgo command installs Go to the user's system. 8 package main 9 10 import ( 11 "bufio" 12 "context" 13 "errors" 14 "flag" 15 "fmt" 16 "os" 17 "os/exec" 18 "strings" 19 ) 20 21 var ( 22 interactive = flag.Bool("i", false, "Interactive mode, prompt for inputs.") 23 verbose = flag.Bool("v", false, "Verbose.") 24 setupOnly = flag.Bool("skip-dl", false, "Don't download - only set up environment variables") 25 goVersion = flag.String("version", "", `Version of Go to install (e.g. "1.8.3"). If empty, uses the latest version.`) 26 27 version = "devel" 28 ) 29 30 var errExitCleanly error = errors.New("exit cleanly sentinel value") 31 32 func main() { 33 flag.Parse() 34 if *goVersion != "" && !strings.HasPrefix(*goVersion, "go") { 35 *goVersion = "go" + *goVersion 36 } 37 38 ctx := context.Background() 39 40 verbosef("version " + version) 41 42 runStep := func(s step) { 43 err := s(ctx) 44 if err == errExitCleanly { 45 os.Exit(0) 46 } 47 if err != nil { 48 fmt.Fprintln(os.Stderr, err) 49 os.Exit(2) 50 } 51 } 52 53 if !*setupOnly { 54 runStep(welcome) 55 runStep(checkOthers) 56 runStep(chooseVersion) 57 runStep(downloadGo) 58 } 59 60 runStep(setupGOPATH) 61 } 62 63 func verbosef(format string, v ...interface{}) { 64 if !*verbose { 65 return 66 } 67 68 fmt.Printf(format+"\n", v...) 69 } 70 71 func prompt(ctx context.Context, query, defaultAnswer string) (string, error) { 72 if !*interactive { 73 return defaultAnswer, nil 74 } 75 76 fmt.Printf("%s [%s]: ", query, defaultAnswer) 77 78 type result struct { 79 answer string 80 err error 81 } 82 ch := make(chan result, 1) 83 go func() { 84 s := bufio.NewScanner(os.Stdin) 85 if !s.Scan() { 86 ch <- result{"", s.Err()} 87 return 88 } 89 answer := s.Text() 90 if answer == "" { 91 answer = defaultAnswer 92 } 93 ch <- result{answer, nil} 94 }() 95 96 select { 97 case r := <-ch: 98 return r.answer, r.err 99 case <-ctx.Done(): 100 return "", ctx.Err() 101 } 102 } 103 104 func runCommand(ctx context.Context, prog string, args ...string) ([]byte, error) { 105 verbosef("Running command: %s %v", prog, args) 106 107 cmd := exec.CommandContext(ctx, prog, args...) 108 out, err := cmd.CombinedOutput() 109 if err != nil { 110 return nil, fmt.Errorf("running cmd '%s %s' failed: %s err: %v", prog, strings.Join(args, " "), string(out), err) 111 } 112 if out != nil && err == nil && len(out) != 0 { 113 verbosef("%s", out) 114 } 115 116 return out, nil 117 }