Merge pull request #10 from jbfarez/feature/custom-version-support

Add support to pass custom version to fetch from Github
This commit is contained in:
Linda_pp 2018-03-21 19:05:43 +09:00 committed by GitHub
commit c0c9635893
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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.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.UpdateCommand()`: Detect the latest version of given repository and update given command.
- `selfupdate.DetectLatest()`: Detect the latest version of given repository. - `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.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 - `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 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`. `{.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. 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. 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+`) var reVersion = regexp.MustCompile(`\d+\.\d+\.\d+`)
func findAssetFromReleasse(rel *github.RepositoryRelease, suffixes []string) (*github.ReleaseAsset, semver.Version, bool) { func findAssetFromReleasse(rel *github.RepositoryRelease, suffixes []string, targetVersion string) (*github.ReleaseAsset, semver.Version, bool) {
if rel.GetDraft() { 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()) log.Println("Skip draft version", rel.GetTagName())
return nil, semver.Version{}, false return nil, semver.Version{}, false
} }
if rel.GetPrerelease() { if targetVersion == "" && rel.GetPrerelease() {
log.Println("Skip pre-release version", rel.GetTagName()) log.Println("Skip pre-release version", rel.GetTagName())
return nil, semver.Version{}, false return nil, semver.Version{}, false
} }
@ -54,8 +59,8 @@ func findAssetFromReleasse(rel *github.RepositoryRelease, suffixes []string) (*g
return nil, semver.Version{}, false return nil, semver.Version{}, false
} }
func findReleaseAndAsset(rels []*github.RepositoryRelease) (*github.RepositoryRelease, *github.ReleaseAsset, semver.Version, bool) { func findReleaseAndAsset(rels []*github.RepositoryRelease, targetVersion string) (*github.RepositoryRelease, *github.ReleaseAsset, semver.Version, bool) {
// Generate valid suffix candidates to match // Generate candidates
suffixes := make([]string, 0, 2*7*2) suffixes := make([]string, 0, 2*7*2)
for _, sep := range []rune{'_', '-'} { for _, sep := range []rune{'_', '-'} {
for _, ext := range []string{".zip", ".tar.gz", ".gzip", ".gz", ".tar.xz", ".xz", ""} { 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. // Returned list from GitHub API is in the order of the date when created.
// ref: https://github.com/rhysd/go-github-selfupdate/issues/11 // ref: https://github.com/rhysd/go-github-selfupdate/issues/11
for _, rel := range rels { 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. // Note: any version with suffix is less than any version without suffix.
// e.g. 0.0.1 > 0.0.1-beta // e.g. 0.0.1 > 0.0.1-beta
if release == nil || v.GTE(ver) { 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. // 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'. // 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'. // 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, "/") repo := strings.Split(slug, "/")
if len(repo) != 2 || repo[0] == "" || repo[1] == "" { if len(repo) != 2 || repo[0] == "" || repo[1] == "" {
return nil, false, fmt.Errorf("Invalid slug format. It should be 'owner/name': %s", slug) 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 return nil, false, err
} }
rel, asset, ver, found := findReleaseAndAsset(rels) rel, asset, ver, found := findReleaseAndAsset(rels, version)
if !found { if !found {
return nil, false, nil 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) log.Println("Successfully fetched the latest release. tag:", rel.GetTagName(), ", name:", rel.GetName(), ", URL:", rel.GetURL(), ", Asset:", url)
publishedAt := rel.GetPublishedAt().Time publishedAt := rel.GetPublishedAt().Time
release := &Release{ release = &Release{
ver, ver,
url, url,
asset.GetSize(), asset.GetSize(),
@ -147,3 +158,8 @@ func (up *Updater) DetectLatest(slug string) (*Release, bool, error) {
func DetectLatest(slug string) (*Release, bool, error) { func DetectLatest(slug string) (*Release, bool, error) {
return DefaultUpdater().DetectLatest(slug) 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 ( import (
"fmt" "fmt"
"github.com/blang/semver"
"os" "os"
"strings" "strings"
"testing" "testing"
"github.com/blang/semver"
) )
func TestDetectReleaseWithVersionPrefix(t *testing.T) { 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) { func TestDetectReleasesForVariousArchives(t *testing.T) {
for _, tc := range []struct { for _, tc := range []struct {
slug string slug string