You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
2.3 KiB

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