Skip to content

Commit

Permalink
Create RepositoryRefsOptions and ListRefs method with helper funds (#155
Browse files Browse the repository at this point in the history
)

* Create Rep Ref Options type

* Create list refs functions

This commit creates a ListRefs method of the Repository type.
Specifically, it creates a RepositoryRefs struct type that is returned
from the decoodeRepositoryRefs function that is a helper function
for decoding the reponse from the refs GET API Bitbucket endpoint.

* Correct Options type and add documentation

* Create test for ListRefs

This commit creates a test case for ListRefs based on setting up the
test repo with a new branch and then listing the refs and making sure
properly created the test repo. So, this test case technically also
tests a portion of the functionality of the CreateBranch function.
  • Loading branch information
DataDavD authored Jul 30, 2021
1 parent 23fc175 commit f3ac86c
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 0 deletions.
15 changes: 15 additions & 0 deletions bitbucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,21 @@ type RepositoryBlobWriteOptions struct {
Branch string `json:"branch"`
}

// RepositoryRefOptions represents the options for describing a repository's refs (i.e.
// tags and branches). The field BranchFlg is a boolean that is indicates whether a specific
// RepositoryRefOptions instance is meant for Branch specific set of api methods.
type RepositoryRefOptions struct {
Owner string `json:"owner"`
RepoSlug string `json:"repo_slug"`
Query string `json:"query"`
Sort string `json:"sort"`
PageNum int `json:"page"`
Pagelen int `json:"pagelen"`
MaxDepth int `json:"max_depth"`
Name string `json:"name"`
BranchFlg bool
}

type RepositoryBranchOptions struct {
Owner string `json:"owner"`
RepoSlug string `json:"repo_slug"`
Expand Down
99 changes: 99 additions & 0 deletions repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ type RepositoryBlob struct {
Content []byte
}

type RepositoryRefs struct {
Page int
Pagelen int
MaxDepth int
Size int
Next string
Refs []map[string]interface{}
}

type RepositoryBranches struct {
Page int
Pagelen int
Expand Down Expand Up @@ -278,6 +287,44 @@ func (r *Repository) WriteFileBlob(ro *RepositoryBlobWriteOptions) error {
return err
}

// ListRefs gets all refs in the Bitbucket repository and returns them as a RepositoryRefs.
// It takes in a RepositoryRefOptions instance as its only parameter.
func (r *Repository) ListRefs(rbo *RepositoryRefOptions) (*RepositoryRefs, error) {

params := url.Values{}
if rbo.Query != "" {
params.Add("q", rbo.Query)
}

if rbo.Sort != "" {
params.Add("sort", rbo.Sort)
}

if rbo.PageNum > 0 {
params.Add("page", strconv.Itoa(rbo.PageNum))
}

if rbo.Pagelen > 0 {
params.Add("pagelen", strconv.Itoa(rbo.Pagelen))
}

if rbo.MaxDepth > 0 {
params.Add("max_depth", strconv.Itoa(rbo.MaxDepth))
}

urlStr := r.c.requestUrl("/repositories/%s/%s/refs?%s", rbo.Owner, rbo.RepoSlug, params.Encode())
response, err := r.c.executeRaw("GET", urlStr, "")
if err != nil {
return nil, err
}
bodyBytes, err := ioutil.ReadAll(response)
if err != nil {
return nil, err
}
bodyString := string(bodyBytes)
return decodeRepositoryRefs(bodyString)
}

func (r *Repository) ListBranches(rbo *RepositoryBranchOptions) (*RepositoryBranches, error) {

params := url.Values{}
Expand Down Expand Up @@ -911,6 +958,58 @@ func decodeRepositoryFiles(repoResponse interface{}) ([]RepositoryFile, error) {
return *repositoryFiles, nil
}

func decodeRepositoryRefs(refResponseStr string) (*RepositoryRefs, error) {

var refResponseMap map[string]interface{}
err := json.Unmarshal([]byte(refResponseStr), &refResponseMap)
if err != nil {
return nil, err
}

refArray := refResponseMap["values"].([]interface{})
var refs []map[string]interface{}
for _, refEntry := range refArray {
var ref map[string]interface{}
err = mapstructure.Decode(refEntry, &ref)
if err == nil {
refs = append(refs, ref)
}
}

page, ok := refResponseMap["page"].(float64)
if !ok {
page = 0
}

pagelen, ok := refResponseMap["pagelen"].(float64)
if !ok {
pagelen = 0
}
max_depth, ok := refResponseMap["max_depth"].(float64)
if !ok {
max_depth = 0
}
size, ok := refResponseMap["size"].(float64)
if !ok {
size = 0
}

next, ok := refResponseMap["next"].(string)
if !ok {
next = ""
}

repositoryBranches := RepositoryRefs{
Page: int(page),
Pagelen: int(pagelen),
MaxDepth: int(max_depth),
Size: int(size),
Next: next,
Refs: refs,
}
return &repositoryBranches, nil
}

func decodeRepositoryBranches(branchResponseStr string) (*RepositoryBranches, error) {

var branchResponseMap map[string]interface{}
Expand Down
71 changes: 71 additions & 0 deletions tests/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,74 @@ func TestDeleteRepositoryPipelineVariables(t *testing.T) {
t.Error(err)
}
}

func TestGetRepositoryRefs(t *testing.T) {

user := os.Getenv("BITBUCKET_TEST_USERNAME")
pass := os.Getenv("BITBUCKET_TEST_PASSWORD")
owner := os.Getenv("BITBUCKET_TEST_OWNER")
repo := os.Getenv("BITBUCKET_TEST_REPOSLUG")

if user == "" {
t.Error("BITBUCKET_TEST_USERNAME is empty.")
}
if pass == "" {
t.Error("BITBUCKET_TEST_PASSWORD is empty.")
}
if owner == "" {
t.Error("BITBUCKET_TEST_OWNER is empty.")
}
if repo == "" {
t.Error("BITBUCKET_TEST_REPOSLUG is empty.")
}

c := bitbucket.NewBasicAuth(user, pass)

opt := &bitbucket.RepositoryBranchCreationOptions{
Owner: owner,
RepoSlug: repo,
Name: "TestGetRepoRefsBranch",
Target: bitbucket.RepositoryBranchTarget{Hash: "master"},
}

_, err := c.Repositories.Repository.CreateBranch(opt)
if err != nil {
t.Error("Could not create new branch", err)
}

refOpts := &bitbucket.RepositoryRefOptions{
Owner: owner,
RepoSlug: repo,
}

resRefs, err := c.Repositories.Repository.ListRefs(refOpts)
if err != nil {
t.Error("The refs is not found.")
}

expected := struct {
n string
t string
}{}

for _, ref := range resRefs.Refs {
for k, v := range ref {
// kCopy := k
vCopy := v
if val, ok := vCopy.(string); ok {
if k == "name" && val == "TestGetRepoRefsBranch" {
expected.n = val
}
}
if val, ok := vCopy.(string); ok {
if k == "type" && val == "branch" {
expected.t = val
}
}
}
}

if !(expected.n == "TestGetRepoRefsBranch" && expected.t == "branch") {
t.Error("Could not list refs/branch that was created in test setup")
}
}

0 comments on commit f3ac86c

Please sign in to comment.