Add support to pass custom version to fetch from Github

This commit is contained in:
Jean-Baptiste Farez 2018-02-02 12:24:01 +01:00
parent d5c53b8d05
commit a3573534f9
No known key found for this signature in database
GPG Key ID: 2CFADE860E1DEB12
3 changed files with 56 additions and 11 deletions

View File

@ -89,6 +89,7 @@ It provides `selfupdate` package.
- `selfupdate.UpdateSelf()`: Detect the latest version of itself and run self update.
- `selfupdate.UpdateCommand()`: Detect the latest version of given repository and update given command.
- `selfupdate.DetectLatest()`: Detect the latest version of given repository.
- `selfupdate.DetectVersion()`: Detect the user defined version of given repository.
- `selfupdate.UpdateTo()`: Update given command to the binary hosted on given URL.
- `selfupdate.Updater`: Context manager of self-upadte process. If you want to customize some behavior
of self-update (e.g. specify API token, use GitHub Enterprise, ...), please make an instance of
@ -231,7 +232,7 @@ You need to put the binaries with the following format.
`{.ext}` is a file extension. go-github-selfupdate supports `.zip`, `.gzip`, `.tar.gz` and `.tar.xz`.
You can also use blank and it means binary is not compressed.
If you compress binary, uncompressed directory or file must contain the executable named `{cmd}`.
If you compress binary, uncompressed directory or file must contain the executable named `{cmd}`.
And you can also use `-` for separator instead of `_` if you like.

View File

@ -12,12 +12,17 @@ import (
var reVersion = regexp.MustCompile(`\d+\.\d+\.\d+`)
func findAssetFromReleasse(rel *github.RepositoryRelease, suffixes []string) (*github.ReleaseAsset, semver.Version, bool) {
if rel.GetDraft() {
func findAssetFromReleasse(rel *github.RepositoryRelease, suffixes []string, targetVersion string) (*github.ReleaseAsset, semver.Version, bool) {
if targetVersion != "" && targetVersion != rel.GetTagName() {
log.Println("Skip", rel.GetTagName(), "not matching to specified version", targetVersion)
return nil, semver.Version{}, false
}
if targetVersion == "" && rel.GetDraft() {
log.Println("Skip draft version", rel.GetTagName())
return nil, semver.Version{}, false
}
if rel.GetPrerelease() {
if targetVersion == "" && rel.GetPrerelease() {
log.Println("Skip pre-release version", rel.GetTagName())
return nil, semver.Version{}, false
}
@ -54,8 +59,8 @@ func findAssetFromReleasse(rel *github.RepositoryRelease, suffixes []string) (*g
return nil, semver.Version{}, false
}
func findReleaseAndAsset(rels []*github.RepositoryRelease) (*github.RepositoryRelease, *github.ReleaseAsset, semver.Version, bool) {
// Generate valid suffix candidates to match
func findReleaseAndAsset(rels []*github.RepositoryRelease, targetVersion string) (*github.RepositoryRelease, *github.ReleaseAsset, semver.Version, bool) {
// Generate candidates
suffixes := make([]string, 0, 2*7*2)
for _, sep := range []rune{'_', '-'} {
for _, ext := range []string{".zip", ".tar.gz", ".gzip", ".gz", ".tar.xz", ".xz", ""} {
@ -76,7 +81,7 @@ func findReleaseAndAsset(rels []*github.RepositoryRelease) (*github.RepositoryRe
// Returned list from GitHub API is in the order of the date when created.
// ref: https://github.com/rhysd/go-github-selfupdate/issues/11
for _, rel := range rels {
if a, v, ok := findAssetFromReleasse(rel, suffixes); ok {
if a, v, ok := findAssetFromReleasse(rel, suffixes, targetVersion); ok {
// Note: any version with suffix is less than any version without suffix.
// e.g. 0.0.1 > 0.0.1-beta
if release == nil || v.GTE(ver) {
@ -101,7 +106,13 @@ func findReleaseAndAsset(rels []*github.RepositoryRelease) (*github.RepositoryRe
// where 'foo' is a command name. '-' can also be used as a separator. File can be compressed with zip, gzip, zxip, tar&zip or tar&zxip.
// So the asset can have a file extension for the corresponding compression format such as '.zip'.
// On Windows, '.exe' also can be contained such as 'foo_windows_amd64.exe.zip'.
func (up *Updater) DetectLatest(slug string) (*Release, bool, error) {
func (up *Updater) DetectLatest(slug string) (release *Release, found bool, err error) {
return up.DetectVersion(slug, "")
}
// DetectVersion tries to get the give nversion of the repository on Github. `slug` means `owner/name` formatted string.
// And version indicates the required version.
func (up *Updater) DetectVersion(slug string, version string) (release *Release, found bool, err error) {
repo := strings.Split(slug, "/")
if len(repo) != 2 || repo[0] == "" || repo[1] == "" {
return nil, false, fmt.Errorf("Invalid slug format. It should be 'owner/name': %s", slug)
@ -118,7 +129,7 @@ func (up *Updater) DetectLatest(slug string) (*Release, bool, error) {
return nil, false, err
}
rel, asset, ver, found := findReleaseAndAsset(rels)
rel, asset, ver, found := findReleaseAndAsset(rels, version)
if !found {
return nil, false, nil
}
@ -127,7 +138,7 @@ func (up *Updater) DetectLatest(slug string) (*Release, bool, error) {
log.Println("Successfully fetched the latest release. tag:", rel.GetTagName(), ", name:", rel.GetName(), ", URL:", rel.GetURL(), ", Asset:", url)
publishedAt := rel.GetPublishedAt().Time
release := &Release{
release = &Release{
ver,
url,
asset.GetSize(),
@ -147,3 +158,8 @@ func (up *Updater) DetectLatest(slug string) (*Release, bool, error) {
func DetectLatest(slug string) (*Release, bool, error) {
return DefaultUpdater().DetectLatest(slug)
}
// DetectVersion detects the given release of the slug (owner/repo) from its version.
func DetectVersion(slug string, version string) (*Release, bool, error) {
return DefaultUpdater().DetectVersion(slug, version)
}

View File

@ -2,10 +2,11 @@ package selfupdate
import (
"fmt"
"github.com/blang/semver"
"os"
"strings"
"testing"
"github.com/blang/semver"
)
func TestDetectReleaseWithVersionPrefix(t *testing.T) {
@ -51,6 +52,33 @@ func TestDetectReleaseWithVersionPrefix(t *testing.T) {
}
}
func TestDetectVersionExisting(t *testing.T) {
testVersion := "v2.2.0"
r, ok, err := DetectVersion("rhysd/github-clone-all", testVersion)
if err != nil {
t.Fatal("Fetch failed:", err)
}
if !ok {
t.Fatalf("Failed to detect %s", testVersion)
}
if r == nil {
t.Fatal("Release detected but nil returned for it")
}
}
func TestDetectVersionNotExisting(t *testing.T) {
r, ok, err := DetectVersion("rhysd/github-clone-all", "foobar")
if err != nil {
t.Fatal("Fetch failed:", err)
}
if ok {
t.Fatal("Failed to correctly detect foobar")
}
if r != nil {
t.Fatal("Release not detected but got a returned value for it")
}
}
func TestDetectReleasesForVariousArchives(t *testing.T) {
for _, tc := range []struct {
slug string