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