[Add] VersionCheck #215

Merged
lafriks merged 12 commits from 6543/go-sdk:version-check into master 2020-01-27 06:20:55 +00:00
9 changed files with 125 additions and 21 deletions

View File

@ -50,7 +50,7 @@ revive:
test:
@export GITEA_SDK_TEST_URL=${GITEA_SDK_TEST_URL}; export GITEA_SDK_TEST_USERNAME=${GITEA_SDK_TEST_USERNAME}; export GITEA_SDK_TEST_PASSWORD=${GITEA_SDK_TEST_PASSWORD}; \
if [ -z "$(shell curl --noproxy "*" "${GITEA_SDK_TEST_URL}/api/v1/version" 2> /dev/null)" ]; then \echo "No test-instance detected!"; exit 1; else \
cd gitea && $(GO) test -cover -coverprofile coverage.out; \
cd gitea && $(GO) test -race -cover -coverprofile coverage.out; \
fi
.PHONY: test-instance

View File

@ -13,6 +13,9 @@ import (
"io/ioutil"
"net/http"
"strings"
"sync"
"github.com/hashicorp/go-version"
)
var jsonHeader = http.Header{"content-type": []string{"application/json"}}
@ -24,12 +27,14 @@ func Version() string {
// Client represents a Gitea API client.
type Client struct {
url string
accessToken string
username string
password string
sudo string
client *http.Client
url string
	serverVersion string
```go serverVersion string ```
accessToken string
username string
password string
sudo string
client *http.Client
serverVersion *version.Version
versionLock sync.RWMutex
}
// NewClient initializes and returns a API client.

View File

@ -2,4 +2,7 @@ module code.gitea.io/sdk/gitea
go 1.12
require github.com/stretchr/testify v1.4.0
require (
github.com/hashicorp/go-version v1.2.0
github.com/stretchr/testify v1.4.0
)

View File

@ -1,5 +1,7 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

View File

@ -20,12 +20,18 @@ type Reaction struct {
// GetIssueReactions get a list reactions of an issue
func (c *Client) GetIssueReactions(owner, repo string, index int64) ([]*Reaction, error) {
if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil {
return nil, err
}
reactions := make([]*Reaction, 0, 10)
return reactions, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), nil, nil, &reactions)
}
// GetIssueCommentReactions get a list of reactions from a comment of an issue
func (c *Client) GetIssueCommentReactions(owner, repo string, commentID int64) ([]*Reaction, error) {
if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil {
return nil, err
}
reactions := make([]*Reaction, 0, 10)
return reactions, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), nil, nil, &reactions)
}
@ -37,6 +43,9 @@ type editReactionOption struct {
// PostIssueReaction add a reaction to an issue
func (c *Client) PostIssueReaction(owner, repo string, index int64, reaction string) (*Reaction, error) {
if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil {
return nil, err
}
reactionResponse := new(Reaction)
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
if err != nil {
@ -48,6 +57,9 @@ func (c *Client) PostIssueReaction(owner, repo string, index int64, reaction str
// DeleteIssueReaction remove a reaction from an issue
func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction string) error {
if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil {
return err
}
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
if err != nil {
return err
@ -58,6 +70,9 @@ func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction s
// PostIssueCommentReaction add a reaction to a comment of an issue
func (c *Client) PostIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Reaction, error) {
if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil {
return nil, err
}
reactionResponse := new(Reaction)
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
if err != nil {
@ -69,6 +84,9 @@ func (c *Client) PostIssueCommentReaction(owner, repo string, commentID int64, r
// DeleteIssueCommentReaction remove a reaction from a comment of an issue
func (c *Client) DeleteIssueCommentReaction(owner, repo string, commentID int64, reaction string) error {
if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil {
return err
}
// swagger:operation DELETE /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issueDeleteCommentReaction
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
if err != nil {

View File

@ -10,18 +10,27 @@ import (
// GetIssueSubscribers get list of users who subscribed on an issue
func (c *Client) GetIssueSubscribers(owner, repo string, index int64) ([]*User, error) {
if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil {
return nil, err
}
subscribers := make([]*User, 0, 10)
return subscribers, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions", owner, repo, index), nil, nil, &subscribers)
}
// AddIssueSubscription Subscribe user to issue
func (c *Client) AddIssueSubscription(owner, repo string, index int64, user string) error {
if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil {
return err
}
_, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
return err
}
// DeleteIssueSubscription unsubscribe user from issue
func (c *Client) DeleteIssueSubscription(owner, repo string, index int64, user string) error {
if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil {
return err
}
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
return err
}

View File

@ -1,13 +0,0 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
// ServerVersion returns the version of the server
func (c *Client) ServerVersion() (string, error) {
var v = struct {
Version string `json:"version"`
}{}
return v.Version, c.getParsedResponse("GET", "/version", nil, nil, &v)
}

57
gitea/version.go Normal file
View File

@ -0,0 +1,57 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"github.com/hashicorp/go-version"
)

This should be moved into Client struct as field serverVersion string

This should be moved into `Client` struct as field `serverVersion string`
// ServerVersion returns the version of the server
func (c *Client) ServerVersion() (string, error) {
var v = struct {
func (c *Client) ServerVersion() (string, error) {
	if len(c.serverVersion) != 0 {
		return c.serverVersion, nil
	}
	if err := c.ReloadServerVersion(); err != nil {
		return "", err
	}
	return c.serverVersion, nil
}

func (c *Client) ReloadServerVersion() error {
	// Reset cached server version string
	c.serverVersion = ""
	var v = struct {
		Version string `json:"version"`
	}{}
	if err := c.getParsedResponse("GET", "/version", nil, nil, &v) != nil {
		return err
	}
	c.serverVersion = v.Version
	return nil
}
```go func (c *Client) ServerVersion() (string, error) { if len(c.serverVersion) != 0 { return c.serverVersion, nil } if err := c.ReloadServerVersion(); err != nil { return "", err } return c.serverVersion, nil } func (c *Client) ReloadServerVersion() error { // Reset cached server version string c.serverVersion = "" var v = struct { Version string `json:"version"` }{} if err := c.getParsedResponse("GET", "/version", nil, nil, &v) != nil { return err } c.serverVersion = v.Version return nil } ```
Outdated
Review

Why not cache the version here?

Why not cache the version here?
Version string `json:"version"`
}{}
return v.Version, c.getParsedResponse("GET", "/version", nil, nil, &v)
}
// CheckServerVersionConstraint validates that the login's server satisfies a
// given version constraint such as ">= 1.11.0+dev"
func (c *Client) CheckServerVersionConstraint(constraint string) error {
Outdated
Review

I think you should have a lock since there maybe multiple goroutines check the verions.

I think you should have a lock since there maybe multiple goroutines check the verions.
c.versionLock.RLock()
if c.serverVersion == nil {

What if there is error?

What if there is error?
Outdated
Review

raw = "" -> CheckServerVersionConstraint will always end with return fmt.Errorf("gitea se...

raw = "" -> CheckServerVersionConstraint will always end with `return fmt.Errorf("gitea se...`

You can use sync.RWMutex instead to be able to control behavior with errors better

You can use sync.RWMutex instead to be able to control behavior with errors better
c.versionLock.RUnlock()
if err := c.loadClientServerVersion(); err != nil {
return err
}
} else {
c.versionLock.RUnlock()
}
check, err := version.NewConstraint(constraint)
if err != nil {
return err
}
if !check.Check(c.serverVersion) {
return fmt.Errorf("gitea server at %s does not satisfy version constraint %s", c.url, constraint)
}
return nil
}
// loadClientServerVersion init the serverVersion variable
func (c *Client) loadClientServerVersion() error {
c.versionLock.Lock()
defer c.versionLock.Unlock()
raw, err := c.ServerVersion()
if err != nil {
return err
}
if c.serverVersion, err = version.NewVersion(raw); err != nil {
return err
}
return nil
}

23
gitea/version_test.go Normal file
View File

@ -0,0 +1,23 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"log"
"testing"
"github.com/stretchr/testify/assert"
)
func TestVersion(t *testing.T) {
log.Printf("== TestVersion ==")
c := newTestClient()
rawVersion, err := c.ServerVersion()
assert.NoError(t, err)
assert.True(t, true, rawVersion != "")
assert.NoError(t, c.CheckServerVersionConstraint(">= 1.11.0"))
assert.Error(t, c.CheckServerVersionConstraint("< 1.11.0"))
}