github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/cmd/version/version.go (about) 1 // Package version provides the version command. 2 package version 3 4 import ( 5 "context" 6 "errors" 7 "fmt" 8 "io" 9 "net/http" 10 "strings" 11 "time" 12 13 "github.com/coreos/go-semver/semver" 14 "github.com/rclone/rclone/cmd" 15 "github.com/rclone/rclone/fs" 16 "github.com/rclone/rclone/fs/config/flags" 17 "github.com/rclone/rclone/fs/fshttp" 18 "github.com/spf13/cobra" 19 ) 20 21 var ( 22 check = false 23 ) 24 25 func init() { 26 cmd.Root.AddCommand(commandDefinition) 27 cmdFlags := commandDefinition.Flags() 28 flags.BoolVarP(cmdFlags, &check, "check", "", false, "Check for new version", "") 29 } 30 31 var commandDefinition = &cobra.Command{ 32 Use: "version", 33 Short: `Show the version number.`, 34 Long: ` 35 Show the rclone version number, the go version, the build target 36 OS and architecture, the runtime OS and kernel version and bitness, 37 build tags and the type of executable (static or dynamic). 38 39 For example: 40 41 $ rclone version 42 rclone v1.55.0 43 - os/version: ubuntu 18.04 (64 bit) 44 - os/kernel: 4.15.0-136-generic (x86_64) 45 - os/type: linux 46 - os/arch: amd64 47 - go/version: go1.16 48 - go/linking: static 49 - go/tags: none 50 51 Note: before rclone version 1.55 the os/type and os/arch lines were merged, 52 and the "go/version" line was tagged as "go version". 53 54 If you supply the --check flag, then it will do an online check to 55 compare your version with the latest release and the latest beta. 56 57 $ rclone version --check 58 yours: 1.42.0.6 59 latest: 1.42 (released 2018-06-16) 60 beta: 1.42.0.5 (released 2018-06-17) 61 62 Or 63 64 $ rclone version --check 65 yours: 1.41 66 latest: 1.42 (released 2018-06-16) 67 upgrade: https://downloads.rclone.org/v1.42 68 beta: 1.42.0.5 (released 2018-06-17) 69 upgrade: https://beta.rclone.org/v1.42-005-g56e1e820 70 71 `, 72 Annotations: map[string]string{ 73 "versionIntroduced": "v1.33", 74 }, 75 Run: func(command *cobra.Command, args []string) { 76 ctx := context.Background() 77 cmd.CheckArgs(0, 0, command, args) 78 if check { 79 CheckVersion(ctx) 80 } else { 81 cmd.ShowVersion() 82 } 83 }, 84 } 85 86 // strip a leading v off the string 87 func stripV(s string) string { 88 if len(s) > 0 && s[0] == 'v' { 89 return s[1:] 90 } 91 return s 92 } 93 94 // GetVersion gets the version available for download 95 func GetVersion(ctx context.Context, url string) (v *semver.Version, vs string, date time.Time, err error) { 96 resp, err := fshttp.NewClient(ctx).Get(url) 97 if err != nil { 98 return v, vs, date, err 99 } 100 defer fs.CheckClose(resp.Body, &err) 101 if resp.StatusCode != http.StatusOK { 102 return v, vs, date, errors.New(resp.Status) 103 } 104 bodyBytes, err := io.ReadAll(resp.Body) 105 if err != nil { 106 return v, vs, date, err 107 } 108 vs = strings.TrimSpace(string(bodyBytes)) 109 vs = strings.TrimPrefix(vs, "rclone ") 110 vs = strings.TrimRight(vs, "β") 111 date, err = http.ParseTime(resp.Header.Get("Last-Modified")) 112 if err != nil { 113 return v, vs, date, err 114 } 115 v, err = semver.NewVersion(stripV(vs)) 116 return v, vs, date, err 117 } 118 119 // CheckVersion checks the installed version against available downloads 120 func CheckVersion(ctx context.Context) { 121 vCurrent, err := semver.NewVersion(stripV(fs.Version)) 122 if err != nil { 123 fs.Errorf(nil, "Failed to parse version: %v", err) 124 } 125 const timeFormat = "2006-01-02" 126 127 printVersion := func(what, url string) { 128 v, vs, t, err := GetVersion(ctx, url+"version.txt") 129 if err != nil { 130 fs.Errorf(nil, "Failed to get rclone %s version: %v", what, err) 131 return 132 } 133 fmt.Printf("%-8s%-40v %20s\n", 134 what+":", 135 v, 136 "(released "+t.Format(timeFormat)+")", 137 ) 138 if v.Compare(*vCurrent) > 0 { 139 fmt.Printf(" upgrade: %s\n", url+vs) 140 } 141 } 142 fmt.Printf("yours: %-13s\n", vCurrent) 143 printVersion( 144 "latest", 145 "https://downloads.rclone.org/", 146 ) 147 printVersion( 148 "beta", 149 "https://beta.rclone.org/", 150 ) 151 if strings.HasSuffix(fs.Version, "-DEV") { 152 fmt.Println("Your version is compiled from git so comparisons may be wrong.") 153 } 154 }