Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions bitbucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ type repository interface {
UpdatePipelineConfig(opt RepositoryPipelineOptions) (*Pipeline, error)
AddPipelineVariable(opt RepositoryPipelineVariableOptions) (*PipelineVariable, error)
AddPipelineKeyPair(opt RepositoryPipelineKeyPairOptions) (*PipelineKeyPair, error)
ListFiles(opt RepositoryFilesOptions) (*[]RepositoryFile, error)
GetFileBlob(opt RepositoryBlobOptions) (*RepositoryBlob, error)
}

type repositories interface {
Expand Down Expand Up @@ -114,6 +116,19 @@ type RepositoryOptions struct {
Project string `json:"project"`
}

type RepositoryFilesOptions struct {
Owner string `json:"owner"`
RepoSlug string `json:"repo_slug"`
Ref string `json:"ref"`
}

type RepositoryBlobOptions struct {
Owner string `json:"owner"`
RepoSlug string `json:"repo_slug"`
Ref string `json:"ref"`
Path string `json:"path"`
}

type PullRequestsOptions struct {
ID string `json:"id"`
CommentID string `json:"comment_id"`
Expand Down
43 changes: 31 additions & 12 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,21 @@ func injectClient(a *auth) *Client {
return c
}

func (c *Client) executeRaw(method string, urlStr string, text string) ([]byte, error) {
Copy link
Contributor Author

@mfb2 mfb2 Jul 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When requesting file content from Bitbucket, a blob is returned; however, the existing execute and doRequest functions expected a JSON payload to be returned. As such, execute / doRequest in their prior state resulted in errors due to an attempt to parse the response. These new functions were introduced to get the raw payload back from the Bitbucket API and pass that along to the consumer.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right, and I understood it. LGTM! 👍

body := strings.NewReader(text)

req, err := http.NewRequest(method, urlStr, body)
if err != nil {
return nil, err
}
if text != "" {
req.Header.Set("Content-Type", "application/json")
}

c.authenticateRequest(req)
return c.doRawRequest(req, false)
}

func (c *Client) execute(method string, urlStr string, text string) (interface{}, error) {
// Use pagination if changed from default value
const DEC_RADIX = 10
Expand Down Expand Up @@ -263,7 +278,22 @@ func (c *Client) authenticateRequest(req *http.Request) {
}

func (c *Client) doRequest(req *http.Request, emptyResponse bool) (interface{}, error) {
resBodyBytes, err := c.doRawRequest(req, emptyResponse)
if err != nil {
return nil, err
}

var result interface{}
err = json.Unmarshal(resBodyBytes, &result)
if err != nil {
log.Println("Could not unmarshal JSON payload, returning raw response")
return resBodyBytes, err
}

return result, nil
}

func (c *Client) doRawRequest(req *http.Request, emptyResponse bool) ([]byte, error) {
resp, err := c.HttpClient.Do(req)
if err != nil {
return nil, err
Expand All @@ -284,18 +314,7 @@ func (c *Client) doRequest(req *http.Request, emptyResponse bool) (interface{},
return nil, fmt.Errorf("response body is nil")
}

resBodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}

var result interface{}
err = json.Unmarshal(resBodyBytes, &result)
if err != nil {
return nil, err
}

return result, nil
return ioutil.ReadAll(resp.Body)
}

func (c *Client) requestUrl(template string, args ...interface{}) string {
Expand Down
63 changes: 63 additions & 0 deletions repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package bitbucket
import (
"encoding/json"
"os"
"path"

"github.com/k0kubun/pp"
"github.com/mitchellh/mapstructure"
Expand All @@ -26,6 +27,20 @@ type Repository struct {
Links map[string]interface{}
}

type RepositoryFile struct {
Mimetype string
Links map[string]interface{}
Path string
Commit map[string]interface{}
Attributes []string
Type string
Size int
}

type RepositoryBlob struct {
Content []byte
}

type Pipeline struct {
Type string
Enabled bool
Expand Down Expand Up @@ -68,6 +83,30 @@ func (r *Repository) Get(ro *RepositoryOptions) (*Repository, error) {
return decodeRepository(response)
}

func (r *Repository) ListFiles(ro *RepositoryFilesOptions) ([]RepositoryFile, error) {
filePath := path.Join("/repositories", ro.Owner, ro.RepoSlug, "src")
urlStr := r.c.requestUrl(filePath)
response, err := r.c.execute("GET", urlStr, "")
if err != nil {
return nil, err
}

return decodeRepositoryFiles(response)
}

func (r *Repository) GetFileBlob(ro *RepositoryBlobOptions) (*RepositoryBlob, error) {
filePath := path.Join("/repositories", ro.Owner, ro.RepoSlug, "src", ro.Ref, ro.Path)
urlStr := r.c.requestUrl(filePath)
response, err := r.c.executeRaw("GET", urlStr, "")
if err != nil {
return nil, err
}

blob := RepositoryBlob{Content: response}

return &blob, nil
}

func (r *Repository) Delete(ro *RepositoryOptions) (interface{}, error) {
urlStr := r.c.requestUrl("/repositories/%s/%s", ro.Owner, ro.RepoSlug)
return r.c.execute("DELETE", urlStr, "")
Expand Down Expand Up @@ -219,6 +258,22 @@ func decodeRepository(repoResponse interface{}) (*Repository, error) {
return repository, nil
}

func decodeRepositoryFiles(repoResponse interface{}) ([]RepositoryFile, error) {
repoFileMap := repoResponse.(map[string]interface{})

if repoFileMap["type"] == "error" {
return nil, DecodeError(repoFileMap)
}

var repositoryFiles = new([]RepositoryFile)
err := mapstructure.Decode(repoFileMap["values"], repositoryFiles)
if err != nil {
return nil, err
}

return *repositoryFiles, nil
}

func decodePipelineRepository(repoResponse interface{}) (*Pipeline, error) {
repoMap := repoResponse.(map[string]interface{})

Expand Down Expand Up @@ -266,3 +321,11 @@ func decodePipelineKeyPairRepository(repoResponse interface{}) (*PipelineKeyPair

return pipelineKeyPair, nil
}

func (rf RepositoryFile) String() string {
return rf.Path
}

func (rb RepositoryBlob) String() string {
return string(rb.Content)
}