diff --git a/remote/bitbucket/bitbucket.go b/remote/bitbucket/bitbucket.go index e95c9a65b..ed9cf3db6 100644 --- a/remote/bitbucket/bitbucket.go +++ b/remote/bitbucket/bitbucket.go @@ -98,7 +98,7 @@ func (bb *Bitbucket) Login(res http.ResponseWriter, req *http.Request) (*model.U // of organizations, get the orgs and verify the // user is a member. if len(bb.Orgs) != 0 { - resp, err := client.ListTeams(nil) + resp, err := client.ListTeams(&ListOpts{Page: 1, PageLen: 100}) if err != nil { return nil, false, err } @@ -182,7 +182,7 @@ func (bb *Bitbucket) Repos(u *model.User) ([]*model.RepoLite, error) { // var accounts = []string{u.Login} var repos []*model.RepoLite - var page = 1 + // for { // resp, err := client.ListTeams(&ListOpts{Page: page}) // if err != nil { @@ -198,10 +198,11 @@ func (bb *Bitbucket) Repos(u *model.User) ([]*model.RepoLite, error) { // } // } - page = 1 + var page = 1 for { - resp, err := client.ListRepos(u.Login, &ListOpts{Page: page}) + resp, err := client.ListRepos(u.Login, &ListOpts{Page: page, PageLen: 100}) if err != nil { + println(err.Error()) return nil, err } @@ -209,9 +210,12 @@ func (bb *Bitbucket) Repos(u *model.User) ([]*model.RepoLite, error) { repos = append(repos, convertRepoLite(&repo)) } - if resp.Page == resp.Pages { + if len(resp.Next) == 0 { break } + + page = resp.Page + 1 + break } return repos, nil @@ -247,7 +251,28 @@ func (bb *Bitbucket) Perm(u *model.User, owner, name string) (*model.Perm, error // Script fetches the build script (.drone.yml) from the remote // repository and returns in string format. func (bb *Bitbucket) Script(u *model.User, r *model.Repo, b *model.Build) ([]byte, []byte, error) { - return nil, nil, nil + client := NewClientToken( + bb.Client, + bb.Secret, + &oauth2.Token{ + AccessToken: u.Token, + RefreshToken: u.Secret, + }, + ) + + // fetches the .drone.yml for the specified revision. This file + // is required, and will error if not found + config, err := client.FindSource(r.Owner, r.Name, b.Commit, ".drone.yml") + if err != nil { + return nil, nil, err + } + + // fetches the .drone.sec for the specified revision. This file + // is completely optional, therefore we will not return a not + // found error + sec, _ := client.FindSource(r.Owner, r.Name, b.Commit, ".drone.sec") + + return []byte(config.Data), []byte(sec.Data), err } // Status sends the commit status to the remote system. diff --git a/remote/bitbucket/client.go b/remote/bitbucket/client.go index 6e9f296f0..d4d141704 100644 --- a/remote/bitbucket/client.go +++ b/remote/bitbucket/client.go @@ -7,6 +7,7 @@ import ( "io" "net/http" "net/url" + "strconv" "golang.org/x/oauth2" "golang.org/x/oauth2/bitbucket" @@ -54,10 +55,7 @@ func (c *Client) ListEmail() (*EmailResp, error) { func (c *Client) ListTeams(opts *ListOpts) (*AccountResp, error) { var out = new(AccountResp) - var uri = fmt.Sprintf("%s/2.0/teams/?role=member", api) - if opts != nil && opts.Page > 0 { - uri = fmt.Sprintf("%s&page=%d", uri, opts.Page) - } + var uri = fmt.Sprintf("%s/2.0/teams/?role=member&%s", api, encodeListOpts(opts)) var err = c.do(uri, get, nil, out) return out, err } @@ -71,10 +69,7 @@ func (c *Client) FindRepo(owner, name string) (*Repo, error) { func (c *Client) ListRepos(account string, opts *ListOpts) (*RepoResp, error) { var out = new(RepoResp) - var uri = fmt.Sprintf("%s/2.0/repositories/%s", api) - if opts != nil && opts.Page > 0 { - uri = fmt.Sprintf("%s?page=%d", uri, opts.Page) - } + var uri = fmt.Sprintf("%s/2.0/repositories/%s?%s", api, account, encodeListOpts(opts)) var err = c.do(uri, get, nil, out) return out, err } @@ -88,10 +83,7 @@ func (c *Client) FindHook(owner, name, id string) (*Hook, error) { func (c *Client) ListHooks(owner, name string, opts *ListOpts) (*HookResp, error) { var out = new(HookResp) - var uri = fmt.Sprintf("%s/2.0/repositories/%s/%s/hooks", api, owner, name) - if opts != nil && opts.Page > 0 { - uri = fmt.Sprintf("%s?page=%d", uri, opts.Page) - } + var uri = fmt.Sprintf("%s/2.0/repositories/%s/%s/hooks?%s", api, owner, name, encodeListOpts(opts)) var err = c.do(uri, get, nil, out) return out, err } @@ -106,13 +98,20 @@ func (c *Client) DeleteHook(owner, name, id string) error { return c.do(uri, del, nil, nil) } +func (c *Client) FindSource(owner, name, revision, path string) (*Source, error) { + var out = new(Source) + var uri = fmt.Sprintf("%s/1.0/repositories/%s/%s/src/%s/%s", api, owner, name, revision, path) + var err = c.do(uri, get, nil, out) + return out, err +} + func (c *Client) do(rawurl, method string, in, out interface{}) error { uri, err := url.Parse(rawurl) if err != nil { return err } - println(uri.String()) + // if we are posting or putting data, we need to // write it to the body of the request. var buf io.ReadWriter @@ -153,3 +152,17 @@ func (c *Client) do(rawurl, method string, in, out interface{}) error { return nil } + +func encodeListOpts(opts *ListOpts) string { + var params = new(url.Values) + if opts == nil { + return params.Encode() + } + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.PageLen != 0 { + params.Set("pagelen", strconv.Itoa(opts.PageLen)) + } + return params.Encode() +} diff --git a/remote/bitbucket/types.go b/remote/bitbucket/types.go index 8d1adc3b0..1ff14d385 100644 --- a/remote/bitbucket/types.go +++ b/remote/bitbucket/types.go @@ -11,6 +11,7 @@ type AccountResp struct { Page int `json:"page"` Pages int `json:"pagelen"` Size int `json:"size"` + Next string `json:"next"` Values []Account `json:"values"` } @@ -24,6 +25,7 @@ type EmailResp struct { Page int `json:"page"` Pages int `json:"pagelen"` Size int `json:"size"` + Next string `json:"next"` Values []Email `json:"values"` } @@ -39,6 +41,7 @@ type HookResp struct { Page int `json:"page"` Pages int `json:"pagelen"` Size int `json:"size"` + Next string `json:"next"` Values []Hook `json:"values"` } @@ -72,9 +75,17 @@ type RepoResp struct { Page int `json:"page"` Pages int `json:"pagelen"` Size int `json:"size"` + Next string `json:"next"` Values []Repo `json:"values"` } +type Source struct { + Node string `json:"node"` + Path string `json:"path"` + Data string `json:"data"` + Size int64 `json:"size"` +} + type ListOpts struct { Page int PageLen int