File: main.go

package info (click to toggle)
golang-github-rhysd-go-github-selfupdate 1.2.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 348 kB
  • sloc: sh: 21; makefile: 6
file content (132 lines) | stat: -rw-r--r-- 3,063 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package main

import (
	"flag"
	"fmt"
	"github.com/rhysd/go-github-selfupdate/selfupdate"
	"go/build"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

var version = "1.0.0"

func usage() {
	fmt.Fprintln(os.Stderr, `Usage: go-get-release [flags] {package}

  go-get-release is like "go get", but it downloads the latest release from
  GitHub. {package} must start with "github.com/".

Flags:`)
	flag.PrintDefaults()
}

func getCommand(pkg string) string {
	_, cmd := filepath.Split(pkg)
	if cmd == "" {
		// When pkg path is ending with path separator, we need to split it out.
		// i.e. github.com/rhysd/foo/cmd/bar/
		_, cmd = filepath.Split(cmd)
	}
	return cmd
}

func parseSlug(pkg string) (string, bool) {
	pkg = pkg[len("github.com/"):]
	first := false
	for i, r := range pkg {
		if r == '/' {
			if !first {
				first = true
			} else {
				return pkg[:i], true
			}
		}
	}
	if first {
		// When 'github.com/foo/bar' is specified, reaching here.
		return pkg, true
	}
	return "", false
}

func installFrom(url, cmd, path string) error {
	res, err := http.Get(url)
	if err != nil {
		return fmt.Errorf("Failed to download release binary from %s: %s", url, err)
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		return fmt.Errorf("Failed to download release binary from %s: Invalid response ", url)
	}
	executable, err := selfupdate.UncompressCommand(res.Body, url, cmd)
	if err != nil {
		return fmt.Errorf("Failed to uncompress downloaded asset from %s: %s", url, err)
	}
	bin, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0755)
	if err != nil {
		return err
	}
	if _, err := io.Copy(bin, executable); err != nil {
		return fmt.Errorf("Failed to write binary to %s: %s", path, err)
	}
	return nil
}

func main() {
	help := flag.Bool("help", false, "Show help")
	ver := flag.Bool("version", false, "Show version")

	flag.Usage = usage
	flag.Parse()

	if *ver {
		fmt.Println(version)
		os.Exit(0)
	}

	if *help || flag.NArg() != 1 || !strings.HasPrefix(flag.Arg(0), "github.com/") {
		usage()
		os.Exit(1)
	}

	slug, ok := parseSlug(flag.Arg(0))
	if !ok {
		usage()
		os.Exit(1)
	}

	latest, found, err := selfupdate.DetectLatest(slug)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error while detecting the latest version:", err)
		os.Exit(1)
	}
	if !found {
		fmt.Fprintln(os.Stderr, "No release was found in", slug)
		os.Exit(1)
	}

	cmd := getCommand(flag.Arg(0))
	cmdPath := filepath.Join(build.Default.GOPATH, "bin", cmd)
	if _, err := os.Stat(cmdPath); err != nil {
		// When executable is not existing yet
		if err := installFrom(latest.AssetURL, cmd, cmdPath); err != nil {
			fmt.Fprintf(os.Stderr, "Error while installing the release binary from %s: %s\n", latest.AssetURL, err)
			os.Exit(1)
		}
	} else {
		if err := selfupdate.UpdateTo(latest.AssetURL, cmdPath); err != nil {
			fmt.Fprintf(os.Stderr, "Error while replacing the binary with %s: %s\n", latest.AssetURL, err)
			os.Exit(1)
		}
	}

	fmt.Printf(`Command was updated to the latest version %s: %s

Release Notes:
%s
`, latest.Version, cmdPath, latest.ReleaseNotes)
}