switched cvs functions to modules

This commit is contained in:
Andreas Wachter 2021-12-12 19:23:55 +01:00
parent 0ea1ba5036
commit 5015f4fb73
10 changed files with 629 additions and 612 deletions

41
bitbucket/bitbucket.go Normal file
View file

@ -0,0 +1,41 @@
package bitbucket
import (
"gickup/types"
"net/url"
"github.com/ktrysmt/go-bitbucket"
"github.com/rs/zerolog/log"
)
func Get(conf *types.Conf) []types.Repo {
repos := []types.Repo{}
for _, repo := range conf.Source.BitBucket {
client := bitbucket.NewBasicAuth(repo.Username, repo.Password)
if repo.Url == "" {
repo.Url = bitbucket.DEFAULT_BITBUCKET_API_BASE_URL
} else {
bitbucketUrl, err := url.Parse(repo.Url)
if err != nil {
log.Panic().Str("stage", "bitbucket").Str("url", repo.Url).Msg(err.Error())
}
client.SetApiBaseURL(*bitbucketUrl)
}
log.Info().Str("stage", "bitbucket").Str("url", repo.Url).Msgf("grabbing repositories from %s", repo.User)
repositories, err := client.Repositories.ListForAccount(&bitbucket.RepositoriesOptions{Owner: repo.User})
if err != nil {
log.Panic().Str("stage", "bitbucket").Str("url", repo.Url).Msg(err.Error())
}
exclude := types.GetExcludedMap(repo.Exclude)
for _, r := range repositories.Items {
if exclude[r.Name] {
continue
}
repos = append(repos, types.Repo{Name: r.Name, Url: r.Links["clone"].([]interface{})[0].(map[string]interface{})["href"].(string), SshUrl: r.Links["clone"].([]interface{})[1].(map[string]interface{})["href"].(string), Token: "", Defaultbranch: r.Mainbranch.Name, Origin: repo})
}
}
return repos
}

90
gitea/gitea.go Normal file
View file

@ -0,0 +1,90 @@
package gitea
import (
"gickup/types"
"code.gitea.io/sdk/gitea"
"github.com/rs/zerolog/log"
)
func Backup(r types.Repo, d types.GenRepo, dry bool) {
if d.Url == "" {
d.Url = "https://gitea.com/"
}
log.Info().Str("stage", "gitea").Str("url", d.Url).Msgf("mirroring %s to %s", types.Blue(r.Name), d.Url)
giteaclient, err := gitea.NewClient(d.Url)
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", d.Url).Msg(err.Error())
}
giteaclient.SetBasicAuth(d.Token, "")
user, _, err := giteaclient.GetMyUserInfo()
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", d.Url).Msg(err.Error())
}
if !dry {
repo, _, err := giteaclient.GetRepo(user.UserName, r.Name)
if err != nil {
opts := gitea.MigrateRepoOption{RepoName: r.Name, RepoOwner: user.UserName, Mirror: true, CloneAddr: r.Url, AuthToken: r.Token}
if r.Token == "" {
opts = gitea.MigrateRepoOption{RepoName: r.Name, RepoOwner: user.UserName, Mirror: true, CloneAddr: r.Url, AuthUsername: r.Origin.User, AuthPassword: r.Origin.Password}
}
_, _, err := giteaclient.MigrateRepo(opts)
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", d.Url).Msg(err.Error())
}
log.Info().Str("stage", "gitea").Str("url", d.Url).Msgf("mirrored %s to %s", types.Blue(r.Name), d.Url)
} else {
if repo.Mirror {
log.Info().Str("stage", "gitea").Str("url", d.Url).Msgf("mirror of %s already exists, syncing instead", types.Blue(r.Name))
_, err := giteaclient.MirrorSync(user.UserName, repo.Name)
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", d.Url).Msg(err.Error())
}
log.Info().Str("stage", "gitea").Str("url", d.Url).Msgf("successfully synced %s.", types.Blue(r.Name))
}
}
}
}
func Get(conf *types.Conf) []types.Repo {
repos := []types.Repo{}
for _, repo := range conf.Source.Gitea {
if repo.Url == "" {
repo.Url = "https://gitea.com"
}
log.Info().Str("stage", "gitea").Str("url", repo.Url).Msgf("grabbing repositories from %s", repo.User)
opt := gitea.ListReposOptions{}
opt.PageSize = 50
i := 0
gitearepos := []*gitea.Repository{}
for {
opt.Page = i
client, err := gitea.NewClient(repo.Url)
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", repo.Url).Msg(err.Error())
}
if repo.Token != "" {
client.SetBasicAuth(repo.Token, "")
}
repos, _, err := client.ListUserRepos(repo.User, opt)
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", repo.Url).Msg(err.Error())
}
if len(repos) == 0 {
break
}
gitearepos = append(gitearepos, repos...)
i++
}
exclude := types.GetExcludedMap(repo.Exclude)
for _, r := range gitearepos {
if exclude[r.Name] {
continue
}
repos = append(repos, types.Repo{Name: r.Name, Url: r.CloneURL, SshUrl: r.SSHURL, Token: repo.Token, Defaultbranch: r.DefaultBranch, Origin: repo})
}
}
return repos
}

57
github/github.go Normal file
View file

@ -0,0 +1,57 @@
package github
import (
"context"
"gickup/types"
"github.com/google/go-github/v41/github"
"github.com/rs/zerolog/log"
"golang.org/x/oauth2"
)
func Get(conf *types.Conf) []types.Repo {
repos := []types.Repo{}
for _, repo := range conf.Source.Github {
log.Info().Str("stage", "github").Str("url", "https://github.com").Msgf("grabbing the repositories from %s", repo.User)
client := &github.Client{}
opt := &github.RepositoryListOptions{ListOptions: github.ListOptions{PerPage: 50}}
i := 1
githubrepos := []*github.Repository{}
if repo.Token == "" {
client = github.NewClient(nil)
} else {
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: repo.Token},
)
tc := oauth2.NewClient(context.TODO(), ts)
client = github.NewClient(tc)
}
for {
opt.Page = i
repos, _, err := client.Repositories.List(context.TODO(), repo.User, opt)
if err != nil {
log.Panic().Str("stage", "github").Str("url", "https://github.com").Msg(err.Error())
}
if len(repos) == 0 {
break
}
githubrepos = append(githubrepos, repos...)
i++
}
exclude := types.GetExcludedMap(repo.Exclude)
excludeorgs := types.GetExcludedMap(repo.ExcludeOrgs)
for _, r := range githubrepos {
if exclude[*r.Name] {
continue
}
if excludeorgs[r.GetOwner().GetLogin()] {
continue
}
repos = append(repos, types.Repo{Name: r.GetName(), Url: r.GetCloneURL(), SshUrl: r.GetSSHURL(), Token: repo.Token, Defaultbranch: r.GetDefaultBranch(), Origin: repo})
}
}
return repos
}

138
gitlab/gitlab.go Normal file
View file

@ -0,0 +1,138 @@
package gitlab
import (
"fmt"
"gickup/types"
"strings"
"github.com/rs/zerolog/log"
"github.com/xanzy/go-gitlab"
)
func Backup(r types.Repo, d types.GenRepo, dry bool) {
gitlabclient := &gitlab.Client{}
var err error
if d.Url == "" {
d.Url = "https://gitlab.com"
gitlabclient, err = gitlab.NewClient(d.Token)
} else {
gitlabclient, err = gitlab.NewClient(d.Token, gitlab.WithBaseURL(d.Url))
}
log.Info().Str("stage", "gitlab").Str("url", d.Url).Msgf("mirroring %s to %s", types.Blue(r.Name), d.Url)
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", d.Url).Msg(err.Error())
}
True := true
opt := gitlab.ListProjectsOptions{Search: &r.Name, Owned: &True}
projects, _, err := gitlabclient.Projects.ListProjects(&opt)
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", d.Url).Msg(err.Error())
}
found := false
for _, p := range projects {
if p.Name == r.Name {
found = true
}
}
if !dry {
if !found {
if r.Token != "" {
splittedurl := strings.Split(r.Url, "//")
r.Url = fmt.Sprintf("%s//%s@%s", splittedurl[0], r.Token, splittedurl[1])
if r.Token == "" {
r.Url = fmt.Sprintf("%s//%s:%s@%s", splittedurl[0], r.Origin.User, r.Origin.Password, splittedurl[1])
}
}
opts := &gitlab.CreateProjectOptions{Mirror: &True, ImportURL: &r.Url, Name: &r.Name}
_, _, err := gitlabclient.Projects.CreateProject(opts)
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", d.Url).Msg(err.Error())
}
}
}
}
func Get(conf *types.Conf) []types.Repo {
repos := []types.Repo{}
for _, repo := range conf.Source.Gitlab {
if repo.Url == "" {
repo.Url = "https://gitlab.com"
}
log.Info().Str("stage", "gitlab").Str("url", repo.Url).Msgf("grabbing repositories from %s", repo.User)
gitlabrepos := []*gitlab.Project{}
gitlabgrouprepos := []*gitlab.Project{}
client, err := gitlab.NewClient(repo.Token, gitlab.WithBaseURL(repo.Url))
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", repo.Url).Msg(err.Error())
}
opt := &gitlab.ListProjectsOptions{}
users, _, err := client.Users.ListUsers(&gitlab.ListUsersOptions{Username: &repo.User})
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", repo.Url).Msg(err.Error())
}
opt.PerPage = 50
i := 0
for _, user := range users {
if user.Username == repo.User {
for {
projects, _, err := client.Projects.ListUserProjects(user.ID, opt)
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", repo.Url).Msg(err.Error())
}
if len(projects) == 0 {
break
}
gitlabrepos = append(gitlabrepos, projects...)
i++
opt.Page = i
}
}
}
exclude := types.GetExcludedMap(repo.Exclude)
for _, r := range gitlabrepos {
if exclude[r.Name] {
continue
}
repos = append(repos, types.Repo{Name: r.Name, Url: r.HTTPURLToRepo, SshUrl: r.SSHURLToRepo, Token: repo.Token, Defaultbranch: r.DefaultBranch, Origin: repo})
}
groups, _, err := client.Groups.ListGroups(&gitlab.ListGroupsOptions{})
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", repo.Url).Msg(err.Error())
}
visibilities := []gitlab.VisibilityValue{gitlab.PrivateVisibility, gitlab.PublicVisibility, gitlab.InternalVisibility}
for _, visibility := range visibilities {
gopt := &gitlab.ListGroupProjectsOptions{Visibility: gitlab.Visibility(visibility)}
gopt.PerPage = 50
i = 0
for _, group := range groups {
for {
projects, _, err := client.Groups.ListGroupProjects(group.ID, gopt)
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", repo.Url).Msg(err.Error())
}
if len(projects) == 0 {
break
}
gitlabgrouprepos = append(gitlabgrouprepos, projects...)
i++
gopt.Page = i
}
}
for _, r := range gitlabgrouprepos {
if exclude[r.Name] {
continue
}
repos = append(repos, types.Repo{Name: r.Name, Url: r.HTTPURLToRepo, SshUrl: r.SSHURLToRepo, Token: repo.Token, Defaultbranch: r.DefaultBranch, Origin: repo})
}
}
}
return repos
}

6
go.mod
View file

@ -10,16 +10,13 @@ require (
github.com/go-git/go-git/v5 v5.4.2
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-github/v41 v41.0.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/go-github/v41 v41.0.0
github.com/gookit/color v1.5.0
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.0 // indirect
github.com/hashicorp/go-version v1.3.0 // indirect
github.com/k0kubun/pp v3.0.1+incompatible // indirect
github.com/kevinburke/ssh_config v1.1.0 // indirect
github.com/ktrysmt/go-bitbucket v0.9.32
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/melbahja/goph v1.3.0
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/rs/zerolog v1.26.0
@ -31,7 +28,6 @@ require (
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 // indirect
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/yaml.v2 v2.4.0
)

44
go.sum
View file

@ -38,19 +38,14 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/ProtonMail/go-crypto v0.0.0-20210920160938-87db9fbc61c7 h1:DSqTh6nEes/uO8BlNcGk8PzZsxY2sN9ZL//veWBdTRI=
github.com/ProtonMail/go-crypto v0.0.0-20210920160938-87db9fbc61c7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3 h1:XcF0cTDJeiuZ5NU8w7WUDge0HRwwNRmxj/GGk6KSA6g=
github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/alecthomas/kong v0.2.17 h1:URDISCI96MIgcIlQyoCAlhOmrSw6pZScBNkctg8r0W0=
github.com/alecthomas/kong v0.2.17/go.mod h1:ka3VZ8GZNPXv9Ov+j4YNLkI8mTuhXyr/0ktSlqIydQQ=
github.com/alecthomas/kong v0.2.19 h1:qBDfByO5XgWUXyNB4D6OOhGh5Z1eNOwWayDPQJFNWdc=
github.com/alecthomas/kong v0.2.19/go.mod h1:ka3VZ8GZNPXv9Ov+j4YNLkI8mTuhXyr/0ktSlqIydQQ=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
@ -130,7 +125,6 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@ -151,8 +145,6 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk=
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw=
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
@ -176,11 +168,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
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/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
github.com/k0kubun/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40=
github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/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=
@ -195,27 +184,17 @@ 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.27 h1:1VGdeRHpZZyiIIIBjLr62ATbtOOZCJyyaFZeEWHzmOU=
github.com/ktrysmt/go-bitbucket v0.9.27/go.mod h1:FWxy2UK7GlK5b0NSJGc5hPqnssVlkNnsChvyuOf/Xno=
github.com/ktrysmt/go-bitbucket v0.9.32 h1:IVk0m0gdB4OzRRLgxFnqNsfWKPXNdrcvgdpp9BojTpI=
github.com/ktrysmt/go-bitbucket v0.9.32/go.mod h1:FWxy2UK7GlK5b0NSJGc5hPqnssVlkNnsChvyuOf/Xno=
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/melbahja/goph v1.3.0 h1:RAIS7eL2tew/UrNmBpY2NZMxw6fWtOxki9nkrzw8mZY=
github.com/melbahja/goph v1.3.0/go.mod h1:04M6J+mKmwzAOWhO0ABTweHGU3cizOp90WdCoxrn9gQ=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@ -229,8 +208,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.25.0 h1:Rj7XygbUHKUlDPcVdoLyR91fJBsduXj5fRxyqIQj/II=
github.com/rs/zerolog v1.25.0/go.mod h1:7KHcEGe0QZPOm2IE4Kpb5rTh6n1h2hIgS5OOnu1rUaI=
github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE=
github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
@ -245,8 +222,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/xanzy/go-gitlab v0.51.1 h1:wWKLalwx4omxFoHh3PLs9zDgAD4GXDP/uoxwMRCSiWM=
github.com/xanzy/go-gitlab v0.51.1/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE=
github.com/xanzy/go-gitlab v0.52.2 h1:gkgg1z4ON70sphibtD86Bfmt1qV3mZ0pU0CBBCFAEvQ=
github.com/xanzy/go-gitlab v0.52.2/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
@ -257,7 +232,6 @@ github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1z
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@ -274,10 +248,7 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI=
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8=
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -341,11 +312,7 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f h1:1scJEYZBaF48BaG6tYbtxmLcXqwYGSfGcMoStTqkkIw=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c h1:WtYZ93XtWSO5KlOMgPZu7hXY9WhMZpprvlm5VwvAl8c=
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@ -356,8 +323,6 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 h1:B333XXssMuKQeBwiNODx4TupZy7bf4sxFZnN2ZOcvUE=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -408,18 +373,12 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211031064116-611d5d643895 h1:iaNpwpnrgL5jzWS0vCNnfa8HqzxveCFpFx3uC/X4Tps=
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -433,8 +392,6 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -478,7 +435,6 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

62
gogs/gogs.go Normal file
View file

@ -0,0 +1,62 @@
package gogs
import (
"gickup/types"
"github.com/gogs/go-gogs-client"
"github.com/rs/zerolog/log"
)
func Backup(r types.Repo, d types.GenRepo, dry bool) {
log.Info().Str("stage", "gogs").Str("url", d.Url).Msgf("mirroring %s to %s", types.Blue(r.Name), d.Url)
gogsclient := gogs.NewClient(d.Url, d.Token)
user, err := gogsclient.GetSelfInfo()
if err != nil {
log.Panic().Str("stage", "gogs").Str("url", d.Url).Msg(err.Error())
}
if !dry {
repo, err := gogsclient.GetRepo(user.UserName, r.Name)
if err != nil {
opts := gogs.MigrateRepoOption{RepoName: r.Name, UID: int(user.ID), Mirror: true, CloneAddr: r.Url, AuthUsername: r.Token}
if r.Token == "" {
opts = gogs.MigrateRepoOption{RepoName: r.Name, UID: int(user.ID), Mirror: true, CloneAddr: r.Url, AuthUsername: r.Origin.User, AuthPassword: r.Origin.Password}
}
_, err := gogsclient.MigrateRepo(opts)
if err != nil {
log.Panic().Str("stage", "gogs").Str("url", d.Url).Msg(err.Error())
}
} else {
if repo.Mirror {
log.Info().Str("stage", "gogs").Str("url", d.Url).Msgf("mirror of %s already exists, syncing instead", types.Blue(r.Name))
err := gogsclient.MirrorSync(user.UserName, repo.Name)
if err != nil {
log.Panic().Str("stage", "gogs").Str("url", d.Url).Msg(err.Error())
}
log.Info().Str("stage", "gogs").Str("url", d.Url).Msgf("successfully synced %s.", types.Blue(r.Name))
}
}
}
}
func Get(conf *types.Conf) []types.Repo {
repos := []types.Repo{}
for _, repo := range conf.Source.Gogs {
log.Info().Str("stage", "gogs").Str("url", repo.Url).Msgf("grabbing repositories from %s", repo.User)
client := gogs.NewClient(repo.Url, repo.Token)
gogsrepos, err := client.ListUserRepos(repo.User)
if err != nil {
log.Panic().Str("stage", "gogs").Str("url", repo.Url).Msg(err.Error())
}
exclude := types.GetExcludedMap(repo.Exclude)
for _, r := range gogsrepos {
if exclude[r.Name] {
continue
}
repos = append(repos, types.Repo{Name: r.Name, Url: r.CloneURL, SshUrl: r.SSHURL, Token: repo.Token, Defaultbranch: r.DefaultBranch, Origin: repo})
}
}
return repos
}

170
local/local.go Normal file
View file

@ -0,0 +1,170 @@
package local
import (
"gickup/types"
"net"
"os"
"path"
"strings"
"time"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
"github.com/melbahja/goph"
"github.com/rs/zerolog/log"
gossh "golang.org/x/crypto/ssh"
)
func Locally(repo types.Repo, l types.Local, dry bool) {
stat, err := os.Stat(l.Path)
if os.IsNotExist(err) && !dry {
err := os.MkdirAll(l.Path, 0777)
if err != nil {
log.Panic().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
}
stat, _ = os.Stat(l.Path)
}
if stat != nil {
if stat.IsDir() {
os.Chdir(l.Path)
}
}
tries := 5
var auth transport.AuthMethod
if repo.Origin.SSH {
if repo.Origin.SSHKey == "" {
home := os.Getenv("HOME")
repo.Origin.SSHKey = path.Join(home, ".ssh", "id_rsa")
}
auth, err = ssh.NewPublicKeysFromFile("git", repo.Origin.SSHKey, "")
if err != nil {
panic(err)
}
} else if repo.Token != "" {
auth = &http.BasicAuth{
Username: "xyz",
Password: repo.Token,
}
} else if repo.Origin.Username != "" && repo.Origin.Password != "" {
auth = &http.BasicAuth{
Username: repo.Origin.Username,
Password: repo.Origin.Password,
}
}
for x := 1; x <= tries; x++ {
stat, err := os.Stat(repo.Name)
if os.IsNotExist(err) {
log.Info().Str("stage", "locally").Str("path", l.Path).Msgf("cloning %s", types.Green(repo.Name))
if !dry {
url := repo.Url
if repo.Origin.SSH {
url = repo.SshUrl
site := types.Site{}
err := site.GetValues(url)
if err != nil {
log.Panic().Str("stage", "locally").Msg(err.Error())
}
auth, err := goph.Key(repo.Origin.SSHKey, "")
if err != nil {
log.Panic().Str("stage", "locally").Msg(err.Error())
}
_, err = goph.NewConn(&goph.Config{
User: site.User,
Addr: site.Url,
Port: uint(site.Port),
Auth: auth,
Callback: VerifyHost,
})
if err != nil {
log.Panic().Str("stage", "locally").Msg(err.Error())
}
}
_, err = git.PlainClone(repo.Name, false, &git.CloneOptions{
URL: url,
Auth: auth,
SingleBranch: false,
})
if err != nil {
if x == tries {
log.Panic().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
} else {
if strings.Contains(err.Error(), "remote repository is empty") {
log.Warn().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
break
}
log.Warn().Str("stage", "locally").Str("path", l.Path).Msgf("retry %s from %s", types.Red(x), types.Red(tries))
time.Sleep(5 * time.Second)
continue
}
}
}
} else {
if stat.IsDir() {
log.Info().Str("stage", "locally").Str("path", l.Path).Msgf("opening %s locally", types.Green(repo.Name))
r, err := git.PlainOpen(repo.Name)
if err != nil {
log.Panic().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
}
w, err := r.Worktree()
if err != nil {
log.Panic().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
}
log.Info().Str("stage", "locally").Str("path", l.Path).Msgf("pulling %s", types.Green(repo.Name))
if !dry {
err = w.Pull(&git.PullOptions{Auth: auth, RemoteName: "origin", SingleBranch: false})
if err != nil {
if strings.Contains(err.Error(), "already up-to-date") {
log.Info().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
} else {
if x == tries {
log.Panic().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
} else {
os.RemoveAll(repo.Name)
log.Warn().Str("stage", "locally").Str("path", l.Path).Msgf("retry %s from %s", types.Red(x), types.Red(tries))
time.Sleep(5 * time.Second)
continue
}
}
}
}
} else {
log.Warn().Str("stage", "locally").Str("path", l.Path).Msgf("%s is a file", types.Red(repo.Name))
}
}
x = 5
}
}
func VerifyHost(host string, remote net.Addr, key gossh.PublicKey) error {
// Got from the example from https://github.com/melbahja/goph/blob/master/examples/goph/main.go
//
// If you want to connect to new hosts.
// here your should check new connections public keys
// if the key not trusted you shuld return an error
//
// hostFound: is host in known hosts file.
// err: error if key not in known hosts file OR host in known hosts file but key changed!
hostFound, err := goph.CheckKnownHost(host, remote, key, "")
// Host in known hosts but key mismatch!
// Maybe because of MAN IN THE MIDDLE ATTACK!
/*
if hostFound && err != nil {
return err
}
*/
// handshake because public key already exists.
if hostFound && err == nil {
return nil
}
// Add the new host to known hosts file.
return goph.AddKnownHost(host, remote, key, "")
}

587
main.go
View file

@ -1,34 +1,22 @@
package main
import (
"context"
"fmt"
"io/ioutil"
"net"
"net/url"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"time"
"code.gitea.io/sdk/gitea"
"gickup/bitbucket"
"gickup/gitea"
"gickup/github"
"gickup/gitlab"
"gickup/gogs"
"gickup/local"
"gickup/types"
"github.com/alecthomas/kong"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
"github.com/gogs/go-gogs-client"
"github.com/google/go-github/v41/github"
"github.com/gookit/color"
"github.com/ktrysmt/go-bitbucket"
"github.com/melbahja/goph"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/xanzy/go-gitlab"
gossh "golang.org/x/crypto/ssh"
"golang.org/x/oauth2"
"gopkg.in/yaml.v2"
)
@ -48,75 +36,23 @@ func (v dryrunFlag) BeforeApply() error {
}
var cli struct {
Configfile string `arg required name:"conf" help:"path to the configfile." type:"existingfile"`
Configfile string `arg requitypes.Red name:"conf" help:"path to the configfile." type:"existingfile"`
Version versionFlag
Dry dryrunFlag `flag name:"dryrun" help:"make a dry-run."`
}
var (
red = color.FgRed.Render
green = color.FgGreen.Render
blue = color.FgBlue.Render
dry = false
dry = false
)
func (s *Site) GetValues(url string) {
if strings.HasPrefix(url, "ssh://") {
url = strings.Split(url, "ssh://")[1]
userurl := strings.Split(url, "@")
s.User = userurl[0]
urlport := strings.Split(userurl[1], ":")
s.Url = urlport[0]
portstring := strings.Split(urlport[1], "/")[0]
port, err := strconv.Atoi(portstring)
if err != nil {
log.Panic().Str("stage", "GetValus").Msg(err.Error())
}
s.Port = port
} else {
userurl := strings.Split(url, "@")
s.User = userurl[0]
urlport := strings.Split(userurl[1], ":")
s.Url = urlport[0]
s.Port = 22
}
}
func VerifyHost(host string, remote net.Addr, key gossh.PublicKey) error {
// Got from the example from https://github.com/melbahja/goph/blob/master/examples/goph/main.go
//
// If you want to connect to new hosts.
// here your should check new connections public keys
// if the key not trusted you shuld return an error
//
// hostFound: is host in known hosts file.
// err: error if key not in known hosts file OR host in known hosts file but key changed!
hostFound, err := goph.CheckKnownHost(host, remote, key, "")
// Host in known hosts but key mismatch!
// Maybe because of MAN IN THE MIDDLE ATTACK!
/*
if hostFound && err != nil {
return err
}
*/
// handshake because public key already exists.
if hostFound && err == nil {
return nil
}
// Add the new host to known hosts file.
return goph.AddKnownHost(host, remote, key, "")
}
func ReadConfigfile(configfile string) *Conf {
func ReadConfigfile(configfile string) *types.Conf {
cfgdata, err := ioutil.ReadFile(configfile)
if err != nil {
log.Panic().Str("stage", "readconfig").Str("file", configfile).Msgf("Cannot open config file from %s", red(configfile))
log.Panic().Str("stage", "readconfig").Str("file", configfile).Msgf("Cannot open config file from %s", types.Red(configfile))
}
t := Conf{}
t := types.Conf{}
err = yaml.Unmarshal([]byte(cfgdata), &t)
@ -127,254 +63,7 @@ func ReadConfigfile(configfile string) *Conf {
return &t
}
func GetExcludedMap(excludes []string) map[string]bool {
excludemap := make(map[string]bool)
for _, exclude := range excludes {
excludemap[exclude] = true
}
return excludemap
}
func Locally(repo Repo, l Local) {
stat, err := os.Stat(l.Path)
if os.IsNotExist(err) && !dry {
err := os.MkdirAll(l.Path, 0777)
if err != nil {
log.Panic().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
}
stat, _ = os.Stat(l.Path)
}
if stat != nil {
if stat.IsDir() {
os.Chdir(l.Path)
}
}
tries := 5
var auth transport.AuthMethod
if repo.Origin.SSH {
if repo.Origin.SSHKey == "" {
home := os.Getenv("HOME")
repo.Origin.SSHKey = path.Join(home, ".ssh", "id_rsa")
}
auth, err = ssh.NewPublicKeysFromFile("git", repo.Origin.SSHKey, "")
if err != nil {
panic(err)
}
} else if repo.Token != "" {
auth = &http.BasicAuth{
Username: "xyz",
Password: repo.Token,
}
} else if repo.Origin.Username != "" && repo.Origin.Password != "" {
auth = &http.BasicAuth{
Username: repo.Origin.Username,
Password: repo.Origin.Password,
}
}
for x := 1; x <= tries; x++ {
stat, err := os.Stat(repo.Name)
if os.IsNotExist(err) {
log.Info().Str("stage", "locally").Str("path", l.Path).Msgf("cloning %s", green(repo.Name))
if !dry {
url := repo.Url
if repo.Origin.SSH {
url = repo.SshUrl
site := Site{}
site.GetValues(url)
auth, err := goph.Key(repo.Origin.SSHKey, "")
if err != nil {
log.Panic().Str("stage", "locally").Msg(err.Error())
}
_, err = goph.NewConn(&goph.Config{
User: site.User,
Addr: site.Url,
Port: uint(site.Port),
Auth: auth,
Callback: VerifyHost,
})
if err != nil {
log.Panic().Str("stage", "locally").Msg(err.Error())
}
}
_, err = git.PlainClone(repo.Name, false, &git.CloneOptions{
URL: url,
Auth: auth,
SingleBranch: false,
})
if err != nil {
if x == tries {
log.Panic().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
} else {
if strings.Contains(err.Error(), "remote repository is empty") {
log.Warn().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
break
}
log.Warn().Str("stage", "locally").Str("path", l.Path).Msgf("retry %s from %s", red(x), red(tries))
time.Sleep(5 * time.Second)
continue
}
}
}
} else {
if stat.IsDir() {
log.Info().Str("stage", "locally").Str("path", l.Path).Msgf("opening %s locally", green(repo.Name))
r, err := git.PlainOpen(repo.Name)
if err != nil {
log.Panic().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
}
w, err := r.Worktree()
if err != nil {
log.Panic().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
}
log.Info().Str("stage", "locally").Str("path", l.Path).Msgf("pulling %s", green(repo.Name))
if !dry {
err = w.Pull(&git.PullOptions{Auth: auth, RemoteName: "origin", SingleBranch: false})
if err != nil {
if strings.Contains(err.Error(), "already up-to-date") {
log.Info().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
} else {
if x == tries {
log.Panic().Str("stage", "locally").Str("path", l.Path).Msg(err.Error())
} else {
os.RemoveAll(repo.Name)
log.Warn().Str("stage", "locally").Str("path", l.Path).Msgf("retry %s from %s", red(x), red(tries))
time.Sleep(5 * time.Second)
continue
}
}
}
}
} else {
log.Warn().Str("stage", "locally").Str("path", l.Path).Msgf("%s is a file", red(repo.Name))
}
}
x = 5
}
}
func BackupGitea(r Repo, d GenRepo) {
if d.Url == "" {
d.Url = "https://gitea.com/"
}
log.Info().Str("stage", "gitea").Str("url", d.Url).Msgf("mirroring %s to %s", blue(r.Name), d.Url)
giteaclient, err := gitea.NewClient(d.Url)
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", d.Url).Msg(err.Error())
}
giteaclient.SetBasicAuth(d.Token, "")
user, _, err := giteaclient.GetMyUserInfo()
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", d.Url).Msg(err.Error())
}
if !dry {
repo, _, err := giteaclient.GetRepo(user.UserName, r.Name)
if err != nil {
opts := gitea.MigrateRepoOption{RepoName: r.Name, RepoOwner: user.UserName, Mirror: true, CloneAddr: r.Url, AuthToken: r.Token}
if r.Token == "" {
opts = gitea.MigrateRepoOption{RepoName: r.Name, RepoOwner: user.UserName, Mirror: true, CloneAddr: r.Url, AuthUsername: r.Origin.User, AuthPassword: r.Origin.Password}
}
_, _, err := giteaclient.MigrateRepo(opts)
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", d.Url).Msg(err.Error())
}
log.Info().Str("stage", "gitea").Str("url", d.Url).Msgf("mirrored %s to %s", blue(r.Name), d.Url)
} else {
if repo.Mirror {
log.Info().Str("stage", "gitea").Str("url", d.Url).Msgf("mirror of %s already exists, syncing instead", blue(r.Name))
_, err := giteaclient.MirrorSync(user.UserName, repo.Name)
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", d.Url).Msg(err.Error())
}
log.Info().Str("stage", "gitea").Str("url", d.Url).Msgf("successfully synced %s.", blue(r.Name))
}
}
}
}
func BackupGogs(r Repo, d GenRepo) {
log.Info().Str("stage", "gogs").Str("url", d.Url).Msgf("mirroring %s to %s", blue(r.Name), d.Url)
gogsclient := gogs.NewClient(d.Url, d.Token)
user, err := gogsclient.GetSelfInfo()
if err != nil {
log.Panic().Str("stage", "gogs").Str("url", d.Url).Msg(err.Error())
}
if !dry {
repo, err := gogsclient.GetRepo(user.UserName, r.Name)
if err != nil {
opts := gogs.MigrateRepoOption{RepoName: r.Name, UID: int(user.ID), Mirror: true, CloneAddr: r.Url, AuthUsername: r.Token}
if r.Token == "" {
opts = gogs.MigrateRepoOption{RepoName: r.Name, UID: int(user.ID), Mirror: true, CloneAddr: r.Url, AuthUsername: r.Origin.User, AuthPassword: r.Origin.Password}
}
_, err := gogsclient.MigrateRepo(opts)
if err != nil {
log.Panic().Str("stage", "gogs").Str("url", d.Url).Msg(err.Error())
}
} else {
if repo.Mirror {
log.Info().Str("stage", "gogs").Str("url", d.Url).Msgf("mirror of %s already exists, syncing instead", blue(r.Name))
err := gogsclient.MirrorSync(user.UserName, repo.Name)
if err != nil {
log.Panic().Str("stage", "gogs").Str("url", d.Url).Msg(err.Error())
}
log.Info().Str("stage", "gogs").Str("url", d.Url).Msgf("successfully synced %s.", blue(r.Name))
}
}
}
}
func BackupGitlab(r Repo, d GenRepo) {
gitlabclient := &gitlab.Client{}
var err error
if d.Url == "" {
d.Url = "https://gitlab.com"
gitlabclient, err = gitlab.NewClient(d.Token)
} else {
gitlabclient, err = gitlab.NewClient(d.Token, gitlab.WithBaseURL(d.Url))
}
log.Info().Str("stage", "gitlab").Str("url", d.Url).Msgf("mirroring %s to %s", blue(r.Name), d.Url)
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", d.Url).Msg(err.Error())
}
True := true
opt := gitlab.ListProjectsOptions{Search: &r.Name, Owned: &True}
projects, _, err := gitlabclient.Projects.ListProjects(&opt)
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", d.Url).Msg(err.Error())
}
found := false
for _, p := range projects {
if p.Name == r.Name {
found = true
}
}
if !dry {
if !found {
if r.Token != "" {
splittedurl := strings.Split(r.Url, "//")
r.Url = fmt.Sprintf("%s//%s@%s", splittedurl[0], r.Token, splittedurl[1])
if r.Token == "" {
r.Url = fmt.Sprintf("%s//%s:%s@%s", splittedurl[0], r.Origin.User, r.Origin.Password, splittedurl[1])
}
}
opts := &gitlab.CreateProjectOptions{Mirror: &True, ImportURL: &r.Url, Name: &r.Name}
_, _, err := gitlabclient.Projects.CreateProject(opts)
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", d.Url).Msg(err.Error())
}
}
}
}
func Backup(repos []Repo, conf *Conf) {
func Backup(repos []types.Repo, conf *types.Conf) {
checkedpath := false
for _, r := range repos {
log.Info().Str("stage", "backup").Msgf("starting backup for %s", r.Url)
@ -387,246 +76,20 @@ func Backup(repos []Repo, conf *Conf) {
conf.Destination.Local[i].Path = path
checkedpath = true
}
Locally(r, d)
local.Locally(r, d, dry)
}
for _, d := range conf.Destination.Gitea {
BackupGitea(r, d)
gitea.Backup(r, d, dry)
}
for _, d := range conf.Destination.Gogs {
BackupGogs(r, d)
gogs.Backup(r, d, dry)
}
for _, d := range conf.Destination.Gitlab {
BackupGitlab(r, d)
gitlab.Backup(r, d, dry)
}
}
}
func getGithub(conf *Conf) []Repo {
repos := []Repo{}
for _, repo := range conf.Source.Github {
log.Info().Str("stage", "github").Str("url", "https://github.com").Msgf("grabbing the repositories from %s", repo.User)
client := &github.Client{}
opt := &github.RepositoryListOptions{ListOptions: github.ListOptions{PerPage: 50}}
i := 1
githubrepos := []*github.Repository{}
if repo.Token == "" {
client = github.NewClient(nil)
} else {
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: repo.Token},
)
tc := oauth2.NewClient(context.TODO(), ts)
client = github.NewClient(tc)
}
for {
opt.Page = i
repos, _, err := client.Repositories.List(context.TODO(), repo.User, opt)
if err != nil {
log.Panic().Str("stage", "github").Str("url", "https://github.com").Msg(err.Error())
}
if len(repos) == 0 {
break
}
githubrepos = append(githubrepos, repos...)
i++
}
exclude := GetExcludedMap(repo.Exclude)
excludeorgs := GetExcludedMap(repo.ExcludeOrgs)
for _, r := range githubrepos {
if exclude[*r.Name] {
continue
}
if excludeorgs[r.GetOwner().GetLogin()] {
continue
}
repos = append(repos, Repo{Name: r.GetName(), Url: r.GetCloneURL(), SshUrl: r.GetSSHURL(), Token: repo.Token, Defaultbranch: r.GetDefaultBranch(), Origin: repo})
}
}
return repos
}
func getGitea(conf *Conf) []Repo {
repos := []Repo{}
for _, repo := range conf.Source.Gitea {
if repo.Url == "" {
repo.Url = "https://gitea.com"
}
log.Info().Str("stage", "gitea").Str("url", repo.Url).Msgf("grabbing repositories from %s", repo.User)
opt := gitea.ListReposOptions{}
opt.PageSize = 50
i := 0
gitearepos := []*gitea.Repository{}
for {
opt.Page = i
client, err := gitea.NewClient(repo.Url)
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", repo.Url).Msg(err.Error())
}
if repo.Token != "" {
client.SetBasicAuth(repo.Token, "")
}
repos, _, err := client.ListUserRepos(repo.User, opt)
if err != nil {
log.Panic().Str("stage", "gitea").Str("url", repo.Url).Msg(err.Error())
}
if len(repos) == 0 {
break
}
gitearepos = append(gitearepos, repos...)
i++
}
exclude := GetExcludedMap(repo.Exclude)
for _, r := range gitearepos {
if exclude[r.Name] {
continue
}
repos = append(repos, Repo{Name: r.Name, Url: r.CloneURL, SshUrl: r.SSHURL, Token: repo.Token, Defaultbranch: r.DefaultBranch, Origin: repo})
}
}
return repos
}
func getGogs(conf *Conf) []Repo {
repos := []Repo{}
for _, repo := range conf.Source.Gogs {
log.Info().Str("stage", "gogs").Str("url", repo.Url).Msgf("grabbing repositories from %s", repo.User)
client := gogs.NewClient(repo.Url, repo.Token)
gogsrepos, err := client.ListUserRepos(repo.User)
if err != nil {
log.Panic().Str("stage", "gogs").Str("url", repo.Url).Msg(err.Error())
}
exclude := GetExcludedMap(repo.Exclude)
for _, r := range gogsrepos {
if exclude[r.Name] {
continue
}
repos = append(repos, Repo{Name: r.Name, Url: r.CloneURL, SshUrl: r.SSHURL, Token: repo.Token, Defaultbranch: r.DefaultBranch, Origin: repo})
}
}
return repos
}
func getGitlab(conf *Conf) []Repo {
repos := []Repo{}
for _, repo := range conf.Source.Gitlab {
if repo.Url == "" {
repo.Url = "https://gitlab.com"
}
log.Info().Str("stage", "gitlab").Str("url", repo.Url).Msgf("grabbing repositories from %s", repo.User)
gitlabrepos := []*gitlab.Project{}
gitlabgrouprepos := []*gitlab.Project{}
client, err := gitlab.NewClient(repo.Token, gitlab.WithBaseURL(repo.Url))
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", repo.Url).Msg(err.Error())
}
opt := &gitlab.ListProjectsOptions{}
users, _, err := client.Users.ListUsers(&gitlab.ListUsersOptions{Username: &repo.User})
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", repo.Url).Msg(err.Error())
}
opt.PerPage = 50
i := 0
for _, user := range users {
if user.Username == repo.User {
for {
projects, _, err := client.Projects.ListUserProjects(user.ID, opt)
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", repo.Url).Msg(err.Error())
}
if len(projects) == 0 {
break
}
gitlabrepos = append(gitlabrepos, projects...)
i++
opt.Page = i
}
}
}
exclude := GetExcludedMap(repo.Exclude)
for _, r := range gitlabrepos {
if exclude[r.Name] {
continue
}
repos = append(repos, Repo{Name: r.Name, Url: r.HTTPURLToRepo, SshUrl: r.SSHURLToRepo, Token: repo.Token, Defaultbranch: r.DefaultBranch, Origin: repo})
}
groups, _, err := client.Groups.ListGroups(&gitlab.ListGroupsOptions{})
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", repo.Url).Msg(err.Error())
}
visibilities := []gitlab.VisibilityValue{gitlab.PrivateVisibility, gitlab.PublicVisibility, gitlab.InternalVisibility}
for _, visibility := range visibilities {
gopt := &gitlab.ListGroupProjectsOptions{Visibility: gitlab.Visibility(visibility)}
gopt.PerPage = 50
i = 0
for _, group := range groups {
for {
projects, _, err := client.Groups.ListGroupProjects(group.ID, gopt)
if err != nil {
log.Panic().Str("stage", "gitlab").Str("url", repo.Url).Msg(err.Error())
}
if len(projects) == 0 {
break
}
gitlabgrouprepos = append(gitlabgrouprepos, projects...)
i++
gopt.Page = i
}
}
for _, r := range gitlabgrouprepos {
if exclude[r.Name] {
continue
}
repos = append(repos, Repo{Name: r.Name, Url: r.HTTPURLToRepo, SshUrl: r.SSHURLToRepo, Token: repo.Token, Defaultbranch: r.DefaultBranch, Origin: repo})
}
}
}
return repos
}
func getBitbucket(conf *Conf) []Repo {
repos := []Repo{}
for _, repo := range conf.Source.BitBucket {
client := bitbucket.NewBasicAuth(repo.Username, repo.Password)
if repo.Url == "" {
repo.Url = bitbucket.DEFAULT_BITBUCKET_API_BASE_URL
} else {
bitbucketUrl, err := url.Parse(repo.Url)
if err != nil {
log.Panic().Str("stage", "bitbucket").Str("url", repo.Url).Msg(err.Error())
}
client.SetApiBaseURL(*bitbucketUrl)
}
log.Info().Str("stage", "bitbucket").Str("url", repo.Url).Msgf("grabbing repositories from %s", repo.User)
repositories, err := client.Repositories.ListForAccount(&bitbucket.RepositoriesOptions{Owner: repo.User})
if err != nil {
log.Panic().Str("stage", "bitbucket").Str("url", repo.Url).Msg(err.Error())
}
exclude := GetExcludedMap(repo.Exclude)
for _, r := range repositories.Items {
if exclude[r.Name] {
continue
}
repos = append(repos, Repo{Name: r.Name, Url: r.Links["clone"].([]interface{})[0].(map[string]interface{})["href"].(string), SshUrl: r.Links["clone"].([]interface{})[1].(map[string]interface{})["href"].(string), Token: "", Defaultbranch: r.Mainbranch.Name, Origin: repo})
}
}
return repos
}
func main() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
@ -634,29 +97,29 @@ func main() {
kong.Parse(&cli, kong.Name("gickup"), kong.Description("a tool to backup all your favorite repos"))
if dry {
log.Info().Str("dry", "true").Msgf("this is a %s", blue("dry run"))
log.Info().Str("dry", "true").Msgf("this is a %s", types.Blue("dry run"))
}
log.Info().Str("file", cli.Configfile).Msgf("Reading %s", green(cli.Configfile))
log.Info().Str("file", cli.Configfile).Msgf("Reading %s", types.Green(cli.Configfile))
conf := ReadConfigfile(cli.Configfile)
// Github
repos := getGithub(conf)
repos := github.Get(conf)
Backup(repos, conf)
// Gitea
repos = getGitea(conf)
repos = gitea.Get(conf)
Backup(repos, conf)
// Gogs
repos = getGogs(conf)
repos = gogs.Get(conf)
Backup(repos, conf)
// Gitlab
repos = getGitlab(conf)
repos = gitlab.Get(conf)
Backup(repos, conf)
//Bitbucket
repos = getBitbucket(conf)
repos = bitbucket.Get(conf)
Backup(repos, conf)
}

View file

@ -1,4 +1,11 @@
package main
package types
import (
"strconv"
"strings"
"github.com/gookit/color"
)
// Destination
type Destination struct {
@ -58,3 +65,40 @@ type Site struct {
User string
Port int
}
func (s *Site) GetValues(url string) error {
if strings.HasPrefix(url, "ssh://") {
url = strings.Split(url, "ssh://")[1]
userurl := strings.Split(url, "@")
s.User = userurl[0]
urlport := strings.Split(userurl[1], ":")
s.Url = urlport[0]
portstring := strings.Split(urlport[1], "/")[0]
port, err := strconv.Atoi(portstring)
if err != nil {
return err
}
s.Port = port
} else {
userurl := strings.Split(url, "@")
s.User = userurl[0]
urlport := strings.Split(userurl[1], ":")
s.Url = urlport[0]
s.Port = 22
}
return nil
}
var (
Red = color.FgRed.Render
Green = color.FgGreen.Render
Blue = color.FgBlue.Render
)
func GetExcludedMap(excludes []string) map[string]bool {
excludemap := make(map[string]bool)
for _, exclude := range excludes {
excludemap[exclude] = true
}
return excludemap
}