118 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
// Copyright 2017 The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
// +build !plan9
 | 
						|
 | 
						|
// The getgo command installs Go to the user's system.
 | 
						|
package main
 | 
						|
 | 
						|
import (
 | 
						|
	"bufio"
 | 
						|
	"context"
 | 
						|
	"errors"
 | 
						|
	"flag"
 | 
						|
	"fmt"
 | 
						|
	"os"
 | 
						|
	"os/exec"
 | 
						|
	"strings"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	interactive = flag.Bool("i", false, "Interactive mode, prompt for inputs.")
 | 
						|
	verbose     = flag.Bool("v", false, "Verbose.")
 | 
						|
	setupOnly   = flag.Bool("skip-dl", false, "Don't download - only set up environment variables")
 | 
						|
	goVersion   = flag.String("version", "", `Version of Go to install (e.g. "1.8.3"). If empty, uses the latest version.`)
 | 
						|
 | 
						|
	version = "devel"
 | 
						|
)
 | 
						|
 | 
						|
var exitCleanly error = errors.New("exit cleanly sentinel value")
 | 
						|
 | 
						|
func main() {
 | 
						|
	flag.Parse()
 | 
						|
	if *goVersion != "" && !strings.HasPrefix(*goVersion, "go") {
 | 
						|
		*goVersion = "go" + *goVersion
 | 
						|
	}
 | 
						|
 | 
						|
	ctx := context.Background()
 | 
						|
 | 
						|
	verbosef("version " + version)
 | 
						|
 | 
						|
	runStep := func(s step) {
 | 
						|
		err := s(ctx)
 | 
						|
		if err == exitCleanly {
 | 
						|
			os.Exit(0)
 | 
						|
		}
 | 
						|
		if err != nil {
 | 
						|
			fmt.Fprintln(os.Stderr, err)
 | 
						|
			os.Exit(2)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if !*setupOnly {
 | 
						|
		runStep(welcome)
 | 
						|
		runStep(checkOthers)
 | 
						|
		runStep(chooseVersion)
 | 
						|
		runStep(downloadGo)
 | 
						|
	}
 | 
						|
 | 
						|
	runStep(setupGOPATH)
 | 
						|
}
 | 
						|
 | 
						|
func verbosef(format string, v ...interface{}) {
 | 
						|
	if !*verbose {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	fmt.Printf(format+"\n", v...)
 | 
						|
}
 | 
						|
 | 
						|
func prompt(ctx context.Context, query, defaultAnswer string) (string, error) {
 | 
						|
	if !*interactive {
 | 
						|
		return defaultAnswer, nil
 | 
						|
	}
 | 
						|
 | 
						|
	fmt.Printf("%s [%s]: ", query, defaultAnswer)
 | 
						|
 | 
						|
	type result struct {
 | 
						|
		answer string
 | 
						|
		err    error
 | 
						|
	}
 | 
						|
	ch := make(chan result, 1)
 | 
						|
	go func() {
 | 
						|
		s := bufio.NewScanner(os.Stdin)
 | 
						|
		if !s.Scan() {
 | 
						|
			ch <- result{"", s.Err()}
 | 
						|
			return
 | 
						|
		}
 | 
						|
		answer := s.Text()
 | 
						|
		if answer == "" {
 | 
						|
			answer = defaultAnswer
 | 
						|
		}
 | 
						|
		ch <- result{answer, nil}
 | 
						|
	}()
 | 
						|
 | 
						|
	select {
 | 
						|
	case r := <-ch:
 | 
						|
		return r.answer, r.err
 | 
						|
	case <-ctx.Done():
 | 
						|
		return "", ctx.Err()
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func runCommand(ctx context.Context, prog string, args ...string) ([]byte, error) {
 | 
						|
	verbosef("Running command: %s %v", prog, args)
 | 
						|
 | 
						|
	cmd := exec.CommandContext(ctx, prog, args...)
 | 
						|
	out, err := cmd.CombinedOutput()
 | 
						|
	if err != nil {
 | 
						|
		return nil, fmt.Errorf("running cmd '%s %s' failed: %s err: %v", prog, strings.Join(args, " "), string(out), err)
 | 
						|
	}
 | 
						|
	if out != nil && err == nil && len(out) != 0 {
 | 
						|
		verbosef("%s", out)
 | 
						|
	}
 | 
						|
 | 
						|
	return out, nil
 | 
						|
}
 |