Skip to content

Commit

Permalink
add bitbucket support
Browse files Browse the repository at this point in the history
Signed-off-by: Tony Worm <tony@hofstadter.io>
  • Loading branch information
verdverm committed Sep 11, 2021
1 parent b6b20da commit 01ec0ec
Show file tree
Hide file tree
Showing 11 changed files with 334 additions and 37 deletions.
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -30,6 +30,7 @@ require (
github.com/kevinburke/ssh_config v1.1.0
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f
github.com/kr/pretty v0.2.0
github.com/ktrysmt/go-bitbucket v0.9.24
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/mattn/go-zglob v0.0.2
github.com/mitchellh/mapstructure v1.3.2 // indirect
Expand Down
12 changes: 12 additions & 0 deletions go.sum
Expand Up @@ -120,6 +120,7 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down Expand Up @@ -203,6 +204,10 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
github.com/k0kubun/pp v2.3.0+incompatible h1:EKhKbi34VQDWJtq+zpsKSEhkHHs9w2P8Izbq8IhLVSo=
github.com/k0kubun/pp v2.3.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kevinburke/ssh_config v1.1.0 h1:pH/t1WS9NzT8go394IqZeJTMHVm6Cr6ZJ6AQ+mdNo/o=
github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
Expand All @@ -219,6 +224,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/ktrysmt/go-bitbucket v0.9.24 h1:8gjKNJ3UMV3Yc+eAc3yrvT45cDy2e41axNwVXHt19kg=
github.com/ktrysmt/go-bitbucket v0.9.24/go.mod h1:FWxy2UK7GlK5b0NSJGc5hPqnssVlkNnsChvyuOf/Xno=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
Expand Down Expand Up @@ -250,6 +257,7 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
Expand Down Expand Up @@ -397,6 +405,7 @@ golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hM
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 h1:xUIPaMhvROX9dhPvRCenIJtU78+lbEenGbgqB5hfHCQ=
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand All @@ -416,6 +425,7 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand All @@ -429,6 +439,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down Expand Up @@ -496,6 +507,7 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
Expand Down
7 changes: 7 additions & 0 deletions lib/mod/cache/fetch.go
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/go-git/go-billy/v5/memfs"

"github.com/hofstadter-io/hof/lib/yagu/repos/bbc"
"github.com/hofstadter-io/hof/lib/yagu/repos/git"
"github.com/hofstadter-io/hof/lib/yagu/repos/github"
"github.com/hofstadter-io/hof/lib/yagu/repos/gitlab"
Expand Down Expand Up @@ -41,6 +42,7 @@ func fetch(lang, mod, ver string, private bool) error {
remote, owner, repo := parseModURL(mod)
tag := ver

fmt.Println("mod/cache.fetch:", lang, remote, owner, repo, ver, private)
// TODO, how to deal with self-hosted / enterprise repos?

switch remote {
Expand All @@ -54,6 +56,11 @@ func fetch(lang, mod, ver string, private bool) error {
return fmt.Errorf("While fetching from gitlab\n%w\n", err)
}

case "bitbucket.org":
if err := bbc.Fetch(FS, owner, repo, tag, private); err != nil {
return fmt.Errorf("While fetching from bitbucket\n%w\n", err)
}

default:
if err := git.Fetch(FS, remote, owner, repo, tag, private); err != nil {
return fmt.Errorf("While fetching from git\n%w\n", err)
Expand Down
21 changes: 2 additions & 19 deletions lib/yagu/git.go
@@ -1,6 +1,7 @@
package yagu

import (
"fmt"
"io/ioutil"
"os"
"strings"
Expand Down Expand Up @@ -70,6 +71,7 @@ func SetupGitOptions(srcUrl, srcVer string) (*git.CloneOptions, error) {
}

func SetupGitAuth(srcUrl, srcVer string, co *git.CloneOptions) error {
fmt.Println("SetupGitAuth")

// GitHub variations
if strings.Contains(srcUrl, "github.com") {
Expand All @@ -80,13 +82,6 @@ func SetupGitAuth(srcUrl, srcVer string, co *git.CloneOptions) error {
}
return nil
}
if os.Getenv("GITHUB_APIKEY") != "" {
co.Auth = &http.BasicAuth{
Username: "github-apikey", // yes, this can be anything except an empty string
Password: os.Getenv("GITHUB_APIKEY"),
}
return nil
}
}

// GitLab variations
Expand All @@ -97,12 +92,6 @@ func SetupGitAuth(srcUrl, srcVer string, co *git.CloneOptions) error {
}
return nil
}
if os.Getenv("GITLAB_APIKEY") != "" {
co.Auth = &http.TokenAuth{
Token: os.Getenv("GITLAB_APIKEY"),
}
return nil
}
if os.Getenv("GITLAB_USERNAME") != "" && os.Getenv("GITLAB_PASSWORD") != "" {
co.Auth = &http.BasicAuth{
Username: os.Getenv("GITLAB_USERNAME"),
Expand All @@ -120,12 +109,6 @@ func SetupGitAuth(srcUrl, srcVer string, co *git.CloneOptions) error {
}
return nil
}
if os.Getenv("BITBUCKET_APIKEY") != "" {
co.Auth = &http.TokenAuth{
Token: os.Getenv("BITBUCKET_APIKEY"),
}
return nil
}
if os.Getenv("BITBUCKET_USERNAME") != "" && os.Getenv("BITBUCKET_PASSWORD") != "" {
co.Auth = &http.BasicAuth{
Username: os.Getenv("BITBUCKET_USERNAME"),
Expand Down
27 changes: 27 additions & 0 deletions lib/yagu/repos/bbc/client.go
@@ -0,0 +1,27 @@
package bbc

import (
"os"

"github.com/ktrysmt/go-bitbucket"
)

const TokenEnv = "BITBUCKET_TOKEN"
const UsernameEnv = "BITBUCKET_USERNAME"
const PasswordEnv = "BITBUCKET_PASSWORD"

func NewClient() (client *bitbucket.Client, err error) {

// if token is empty, it means the same things as unauthenticated setup
if token := os.Getenv(TokenEnv); token != "" {
token := os.Getenv(TokenEnv)
client = bitbucket.NewOAuthbearerToken(token)
} else if password := os.Getenv(PasswordEnv); password != "" {
username := os.Getenv(UsernameEnv)
client = bitbucket.NewBasicAuth(username, password)
} else {
// if token is empty, it means the same things as unauthenticated setup
client = bitbucket.NewOAuthbearerToken("")
}
return client, err
}
159 changes: 159 additions & 0 deletions lib/yagu/repos/bbc/fetch.go
@@ -0,0 +1,159 @@
package bbc

import (
"archive/zip"
"bytes"
"fmt"
"os"
"strings"

"github.com/go-git/go-billy/v5"
"github.com/ktrysmt/go-bitbucket"
"github.com/parnurzeal/gorequest"

"github.com/hofstadter-io/hof/lib/yagu"
"github.com/hofstadter-io/hof/lib/yagu/repos/git"
)

func Fetch(FS billy.Filesystem, owner, repo, tag string, private bool) (error) {
fmt.Println("bbc.Fetch", owner, repo, tag, private)

// If private, and no token auth, try git protocol
// need to catch auth errors and suggest how to setup
if private && os.Getenv(TokenEnv) == "" {
fmt.Println("bitbucket git fallback")
return git.Fetch(FS, "bitbucket.org", owner, repo, tag, private)
}

client, err := NewClient()
if err != nil {
return err
}

var zReader *zip.Reader

if tag == "v0.0.0" {
r, err := GetRepo(client, owner, repo)
if err != nil {
return err
}

zReader, err = FetchBranchZip(owner, repo, r.Mainbranch.Name)
if err != nil {
return fmt.Errorf("While fetching branch zipfile for %s/%s@%s\n%w\n", owner, repo, r.Mainbranch.Name, err)
}

} else {
tags, err := GetTags(client, owner, repo)
if err != nil {
return err
}

// The tag we are looking for
var T *bitbucket.RepositoryTag
for _, t := range tags {
if tag != "" && tag == t.Name {
T = &t
// fmt.Printf("FOUND %v\n", *t.Name)
}
}

if T == nil {
return fmt.Errorf("Did not find tag %q for 'https://bitbucket.org/%s/%s' @%s", tag, owner, repo, tag)
}

zReader, err = FetchTagZip(owner, repo, T.Name)
if err != nil {
fmt.Printf("Error: %v\n", err)
return fmt.Errorf("While fetching tag zipfile\n%w\n", err)
}
}

if err != nil {
return fmt.Errorf("While fetching from bitbucket\n%w\n", err)
}

if err := yagu.BillyLoadFromZip(zReader, FS, true); err != nil {
return fmt.Errorf("While reading zipfile\n%w\n", err)
}

return nil
}

func FetchTagZip(owner, repo, ver string) (*zip.Reader, error) {
fmt.Println("bbc.FetchTagZip")

// url := *tag.ZipballURL
url := fmt.Sprintf("https://bitbucket.org/%s/%s/get/%s.zip", owner, repo, ver)

req := gorequest.New().Get(url)

// TODO, process auth logic here better, maybe find a way to DRY
if token := os.Getenv(TokenEnv); token != "" {
req.Header.Set("Authorization", "Bearer" + token)
} else if password := os.Getenv(PasswordEnv); password != "" {
username := os.Getenv(UsernameEnv)
req.SetBasicAuth(username, password)
}

resp, data, errs := req.EndBytes()

check := "http2: server sent GOAWAY and closed the connection"
if len(errs) != 0 && !strings.Contains(errs[0].Error(), check) {
fmt.Println("errs:", errs)
fmt.Println("resp:", resp)
fmt.Println("body:", len(data))
return nil, errs[0]
}

if len(errs) != 0 || resp.StatusCode >= 500 {
return nil, fmt.Errorf("Internal Error: " + string(resp.StatusCode))
}
if resp.StatusCode >= 400 {
return nil, fmt.Errorf("Bad Request: %v\n%v\n", resp.StatusCode, errs)
}

r := bytes.NewReader(data)

zfile, err := zip.NewReader(r, int64(len(data)))

return zfile, err
}

func FetchBranchZip(owner, repo, branch string) (*zip.Reader, error) {

url := fmt.Sprintf("https://bitbucket.org/%s/%s/get/%s.zip", owner, repo, branch)

req := gorequest.New().Get(url)

// TODO, process auth logic here better, maybe find a way to DRY
if token := os.Getenv(TokenEnv); token != "" {
req.Header.Set("Authorization", "Bearer" + token)
} else if password := os.Getenv(PasswordEnv); password != "" {
username := os.Getenv(UsernameEnv)
req.SetBasicAuth(username, password)
}

resp, data, errs := req.EndBytes()

check := "http2: server sent GOAWAY and closed the connection"
if len(errs) != 0 && !strings.Contains(errs[0].Error(), check) {
fmt.Println("errs:", errs)
fmt.Println("resp:", resp)
fmt.Println("body:", len(data))
return nil, errs[0]
}

if len(errs) != 0 || resp.StatusCode >= 500 {
return nil, fmt.Errorf("Internal Error: " + string(resp.StatusCode))
}
if resp.StatusCode >= 400 {
return nil, fmt.Errorf("Bad Request: " + string(resp.StatusCode))
}

r := bytes.NewReader(data)

zfile, err := zip.NewReader(r, int64(len(data)))

return zfile, err
}

0 comments on commit 01ec0ec

Please sign in to comment.