From f3ac86cd695cd17a1ab80fd70deb60f4f44a4ad6 Mon Sep 17 00:00:00 2001 From: David Dansby <39511285+DataDavD@users.noreply.github.com> Date: Thu, 29 Jul 2021 23:47:20 -0700 Subject: [PATCH] Create RepositoryRefsOptions and ListRefs method with helper funds (#155) * 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. --- bitbucket.go | 15 ++++++ repository.go | 99 ++++++++++++++++++++++++++++++++++++++++ tests/repository_test.go | 71 ++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+) diff --git a/bitbucket.go b/bitbucket.go index 8d63379..ee6a1dd 100644 --- a/bitbucket.go +++ b/bitbucket.go @@ -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"` diff --git a/repository.go b/repository.go index 613cd74..c0f0f3e 100644 --- a/repository.go +++ b/repository.go @@ -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 @@ -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{} @@ -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{} diff --git a/tests/repository_test.go b/tests/repository_test.go index cbdeeb7..3a89bf9 100644 --- a/tests/repository_test.go +++ b/tests/repository_test.go @@ -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") + } +}