-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from matthyx/bitbucket
add support for parsing bitbucket urls
- Loading branch information
Showing
13 changed files
with
560 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package bitbucketapi | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"net/url" | ||
|
||
"github.com/kubescape/go-git-url/apis" | ||
) | ||
|
||
const ( | ||
DEFAULT_HOST string = "bitbucket.org" | ||
) | ||
|
||
type IBitBucketAPI interface { | ||
GetRepoTree(owner, repo, branch string, headers *Headers) (*Tree, error) | ||
GetDefaultBranchName(owner, repo string, headers *Headers) (string, error) | ||
GetLatestCommit(owner, repo, branch string, headers *Headers) (*Commit, error) | ||
} | ||
|
||
type BitBucketAPI struct { | ||
httpClient *http.Client | ||
} | ||
|
||
func NewBitBucketAPI() *BitBucketAPI { return &BitBucketAPI{httpClient: &http.Client{}} } | ||
|
||
func (gl *BitBucketAPI) GetRepoTree(owner, repo, branch string, headers *Headers) (*Tree, error) { | ||
//TODO implement me | ||
return nil, fmt.Errorf("GetRepoTree is not supported") | ||
} | ||
|
||
func (gl *BitBucketAPI) GetDefaultBranchName(owner, repo string, headers *Headers) (string, error) { | ||
body, err := apis.HttpGet(gl.httpClient, APIBranchingModel(owner, repo), headers.ToMap()) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
var data bitbucketBranchingModel | ||
if err = json.Unmarshal([]byte(body), &data); err != nil { | ||
return "", err | ||
} | ||
|
||
return data.Development.Name, nil | ||
} | ||
|
||
func (gl *BitBucketAPI) GetLatestCommit(owner, repo, branch string, headers *Headers) (*Commit, error) { | ||
body, err := apis.HttpGet(gl.httpClient, APILastCommitsOfBranch(owner, repo, branch), headers.ToMap()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var data Commits | ||
err = json.Unmarshal([]byte(body), &data) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &data.Values[0], nil | ||
} | ||
|
||
// APIBranchingModel | ||
// API Ref: https://developer.atlassian.com/cloud/bitbucket/rest/api-group-branching-model/#api-group-branching-model | ||
// Example: https://bitbucket.org/!api/2.0/repositories/matthyx/ks-testing-public/branching-model | ||
func APIBranchingModel(owner, repo string) string { | ||
p, _ := url.JoinPath("!api/2.0/repositories", owner, repo, "branching-model") | ||
u := url.URL{ | ||
Scheme: "https", | ||
Host: DEFAULT_HOST, | ||
Path: p, | ||
} | ||
return u.String() | ||
} | ||
|
||
// APILastCommitsOfBranch | ||
// API Ref: https://developer.atlassian.com/cloud/bitbucket/rest/api-group-commits/#api-repositories-workspace-repo-slug-commits-get | ||
// Example: https://bitbucket.org/!api/2.0/repositories/matthyx/ks-testing-public/commits/?include=master | ||
func APILastCommitsOfBranch(owner, repo, branch string) string { | ||
p, _ := url.JoinPath("!api/2.0/repositories", owner, repo, "commits") | ||
u := url.URL{ | ||
Scheme: "https", | ||
Host: DEFAULT_HOST, | ||
Path: p, | ||
RawQuery: fmt.Sprintf("include=%s", branch), | ||
} | ||
return u.String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package bitbucketapi | ||
|
||
import "time" | ||
|
||
type ObjectType string | ||
|
||
type Tree struct{} | ||
|
||
type bitbucketBranchingModel struct { | ||
Development struct { | ||
Name string `json:"name"` | ||
} `json:"development"` | ||
} | ||
|
||
type Headers struct { | ||
Token string | ||
} | ||
|
||
type Commits struct { | ||
Values []Commit `json:"values"` | ||
Pagelen int `json:"pagelen"` | ||
Next string `json:"next"` | ||
} | ||
|
||
type Commit struct { | ||
Type string `json:"type"` | ||
Hash string `json:"hash"` | ||
Date time.Time `json:"date"` | ||
Author struct { | ||
Type string `json:"type"` | ||
Raw string `json:"raw"` | ||
} `json:"author"` | ||
Message string `json:"message"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package bitbucketapi | ||
|
||
import "fmt" | ||
|
||
// ToMap convert headers to map[string]string | ||
func (h *Headers) ToMap() map[string]string { | ||
m := make(map[string]string) | ||
if h.Token != "" { | ||
m["Authorization"] = fmt.Sprintf("Bearer %s", h.Token) | ||
} | ||
return m | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package v1 | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
"strings" | ||
|
||
"github.com/kubescape/go-git-url/apis" | ||
"github.com/kubescape/go-git-url/apis/bitbucketapi" | ||
) | ||
|
||
var rawUserRe = regexp.MustCompile("([^<]*)?(<(.+)>)?") | ||
|
||
func (gl *BitBucketURL) GetLatestCommit() (*apis.Commit, error) { | ||
if gl.GetHostName() == "" || gl.GetOwnerName() == "" || gl.GetRepoName() == "" { | ||
return nil, fmt.Errorf("missing host/owner/repo") | ||
} | ||
if gl.GetBranchName() == "" { | ||
if err := gl.SetDefaultBranchName(); err != nil { | ||
return nil, fmt.Errorf("failed to get default branch. reason: %s", err.Error()) | ||
} | ||
} | ||
|
||
c, err := gl.bitBucketAPI.GetLatestCommit(gl.GetOwnerName(), gl.GetRepoName(), gl.GetBranchName(), gl.headers()) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get latest commit. reason: %s", err.Error()) | ||
} | ||
|
||
return bitBucketAPICommitToCommit(c), nil | ||
} | ||
|
||
func bitBucketAPICommitToCommit(c *bitbucketapi.Commit) *apis.Commit { | ||
name, email := parseRawUser(c.Author.Raw) | ||
latestCommit := &apis.Commit{ | ||
SHA: c.Hash, | ||
Author: apis.Committer{ | ||
Name: name, | ||
Email: email, | ||
Date: c.Date, | ||
}, | ||
Committer: apis.Committer{ // same as author as API doesn't return the committer | ||
Name: name, | ||
Email: email, | ||
Date: c.Date, | ||
}, | ||
Message: c.Message, | ||
} | ||
|
||
return latestCommit | ||
} | ||
|
||
func parseRawUser(raw string) (string, string) { | ||
match := rawUserRe.FindStringSubmatch(raw) | ||
if match != nil { | ||
return strings.TrimSpace(match[1]), match[3] | ||
} | ||
return raw, "" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package v1 | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_parseRawUser(t *testing.T) { | ||
tests := []struct { | ||
raw string | ||
wantName string | ||
wantEmail string | ||
}{ | ||
{ | ||
raw: "David Wertenteil <dwertent@cyberarmor.io>", | ||
wantName: "David Wertenteil", | ||
wantEmail: "dwertent@cyberarmor.io", | ||
}, | ||
{ | ||
raw: "github-actions[bot] <github-actions[bot]@users.noreply.github.com>", | ||
wantName: "github-actions[bot]", | ||
wantEmail: "github-actions[bot]@users.noreply.github.com", | ||
}, | ||
{ | ||
raw: "David Wertenteil", | ||
wantName: "David Wertenteil", | ||
wantEmail: "", | ||
}, | ||
{ | ||
raw: "<dwertent@cyberarmor.io>", | ||
wantName: "", | ||
wantEmail: "dwertent@cyberarmor.io", | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.raw, func(t *testing.T) { | ||
got, got1 := parseRawUser(tt.raw) | ||
assert.Equalf(t, tt.wantName, got, "parseRawUser(%v)", tt.raw) | ||
assert.Equalf(t, tt.wantEmail, got1, "parseRawUser(%v)", tt.raw) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package v1 | ||
|
||
import ( | ||
"github.com/kubescape/go-git-url/apis/bitbucketapi" | ||
) | ||
|
||
type BitBucketURL struct { | ||
host string | ||
owner string // repo owner | ||
repo string // repo name | ||
project string | ||
branch string | ||
path string | ||
token string // github token | ||
isFile bool | ||
|
||
bitBucketAPI bitbucketapi.IBitBucketAPI | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package v1 | ||
|
||
import "fmt" | ||
|
||
func (gl *BitBucketURL) DownloadAllFiles() (map[string][]byte, map[string]error) { | ||
//TODO implement me | ||
return nil, map[string]error{"": fmt.Errorf("DownloadAllFiles is not supported")} | ||
} | ||
|
||
func (gl *BitBucketURL) DownloadFilesWithExtension(extensions []string) (map[string][]byte, map[string]error) { | ||
//TODO implement me | ||
return nil, map[string]error{"": fmt.Errorf("DownloadFilesWithExtension is not supported")} | ||
} |
Oops, something went wrong.