Skip to content

Commit c8b0dd1

Browse files
authored
Add Gitlab Support (#2)
* Add gitlab support * Add gitlab project selectors * Add docs * Clean up Co-authored-by: Thomas Biesaart <[email protected]>
1 parent d361bd5 commit c8b0dd1

File tree

8 files changed

+183
-954
lines changed

8 files changed

+183
-954
lines changed

README.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,27 @@ github:
3535
# organisations of which you are a member.
3636
# (default: true)
3737
org_member: true
38+
# The gitlab section contains backup jobs for
39+
# GitLab.com and GitLab on premise
40+
gitlab:
41+
# (optional) The job name. This is used to
42+
# create a subfolder in the backup folder.
43+
# (default: GitLab)
44+
- job_name: gitlab.com
45+
# (required) The GitLab access token.
46+
# Create one with the scopes: "api"
47+
# https://gitlab.com/-/profile/personal_access_tokens?scopes=api&name=git-backup
48+
access_token: glpat-6t78yuihy789uy8t768
49+
# (optional) Back up repos you own.
50+
# (default: true)
51+
owned: true
52+
# (optional) Back up repos you starred.
53+
# (default: true)
54+
starred: true
55+
# (optional) Back up repos owned by
56+
# teams of which you are a member.
57+
# (default: true)
58+
member: true
3859
```
3960
4061
## Usage
@@ -47,4 +68,4 @@ Options:
4768
The target path to the backup folder. (default "backup")
4869
-config.file string
4970
The path to your config file. (default "git-backup.yml")
50-
```
71+
```

cmd/git-backup/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,4 @@ func loadConfig() gitbackup.Config {
5555
os.Exit(1)
5656
}
5757
return config
58-
}
58+
}

config.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,19 @@ import (
88

99
type Config struct {
1010
Github []*GithubConfig `yaml:"github"`
11+
GitLab []*GitLabConfig `yaml:"gitlab"`
1112
}
1213

1314
func (c *Config) GetSources() []RepositorySource {
14-
sources := make([]RepositorySource, len(c.Github))
15+
sources := make([]RepositorySource, len(c.Github)+len(c.GitLab))
1516

1617
offset := 0
1718
for i := 0; i < len(c.Github); i++ {
18-
sources[i+offset] = c.Github[i]
19+
sources[offset] = c.Github[i]
20+
offset++
21+
}
22+
for i := 0; i < len(c.GitLab); i++ {
23+
sources[offset] = c.GitLab[i]
1924
offset++
2025
}
2126

@@ -28,6 +33,11 @@ func (c *Config) setDefaults() {
2833
config.setDefaults()
2934
}
3035
}
36+
if c.GitLab != nil {
37+
for _, config := range c.GitLab {
38+
config.setDefaults()
39+
}
40+
}
3141
}
3242

3343
func LoadFile(path string) (out Config, err error) {

github.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ import (
1010
"strings"
1111
)
1212

13-
func boolPointer(b bool) *bool {
14-
return &b
15-
}
16-
1713
type GithubConfig struct {
1814
JobName string `yaml:"job_name"`
1915
AccessToken string `yaml:"access_token"`
@@ -167,4 +163,4 @@ func (c *GithubConfig) getStarredRepos(page int) ([]*github.Repository, *github.
167163
repos[i] = starred[i].Repository
168164
}
169165
return repos, response, err
170-
}
166+
}

gitlab.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package git_backup
2+
3+
import (
4+
"github.com/xanzy/go-gitlab"
5+
"log"
6+
"net/url"
7+
)
8+
9+
type GitLabConfig struct {
10+
URL string `yaml:"url,omitempty"`
11+
JobName string `yaml:"job_name"`
12+
AccessToken string `yaml:"access_token"`
13+
Starred *bool `yaml:"starred,omitempty"`
14+
Member *bool `yaml:"member,omitempty"`
15+
Owned *bool `yaml:"owned,omitempty"`
16+
client *gitlab.Client
17+
}
18+
19+
func (g *GitLabConfig) GetName() string {
20+
return g.JobName
21+
}
22+
23+
func (g *GitLabConfig) Test() error {
24+
user, _, err := g.client.Users.CurrentUser()
25+
if err != nil {
26+
return err
27+
}
28+
log.Printf("Authenticated as with gitlab as: %s", user.Username)
29+
return nil
30+
}
31+
32+
func (g *GitLabConfig) ListRepositories() ([]*Repository, error) {
33+
out := make(map[string]*Repository, 0)
34+
35+
if *g.Starred {
36+
if repos, err := g.getAllRepos(&gitlab.ListProjectsOptions{Starred: boolPointer(true)}); err != nil {
37+
return nil, err
38+
} else {
39+
for _, repo := range repos {
40+
out[repo.FullName] = repo
41+
}
42+
}
43+
}
44+
45+
if *g.Owned {
46+
if repos, err := g.getAllRepos(&gitlab.ListProjectsOptions{Owned: boolPointer(true)}); err != nil {
47+
return nil, err
48+
} else {
49+
for _, repo := range repos {
50+
out[repo.FullName] = repo
51+
}
52+
}
53+
}
54+
55+
if *g.Member {
56+
if repos, err := g.getAllRepos(&gitlab.ListProjectsOptions{Membership: boolPointer(true)}); err != nil {
57+
return nil, err
58+
} else {
59+
for _, repo := range repos {
60+
out[repo.FullName] = repo
61+
}
62+
}
63+
}
64+
65+
outSlice := make([]*Repository, 0, len(out))
66+
for _, repository := range out {
67+
outSlice = append(outSlice, repository)
68+
}
69+
70+
return outSlice, nil
71+
}
72+
73+
func (g *GitLabConfig) getAllRepos(opts *gitlab.ListProjectsOptions) ([]*Repository, error) {
74+
out := make([]*Repository, 0)
75+
for i := 1; true; i++ {
76+
opts.ListOptions.Page = i
77+
repos, _, err := g.getRepos(opts)
78+
if err != nil {
79+
return out, err
80+
}
81+
for _, repo := range repos {
82+
gitUrl, err := url.Parse(repo.HTTPURLToRepo)
83+
if err != nil {
84+
return out, err
85+
}
86+
gitUrl.User = url.UserPassword("git", g.AccessToken)
87+
out = append(out, &Repository{
88+
GitURL: *gitUrl,
89+
FullName: repo.PathWithNamespace,
90+
})
91+
}
92+
if len(repos) == 0 {
93+
break
94+
}
95+
}
96+
return out, nil
97+
}
98+
99+
func (g *GitLabConfig) getRepos(opts *gitlab.ListProjectsOptions) ([]*gitlab.Project, *gitlab.Response, error) {
100+
opts.ListOptions.PerPage = 100
101+
opts.Simple = boolPointer(true)
102+
return g.client.Projects.ListProjects(opts)
103+
}
104+
105+
func (g *GitLabConfig) setDefaults() {
106+
if g.Member == nil {
107+
g.Member = boolPointer(true)
108+
}
109+
if g.Owned == nil {
110+
g.Owned = boolPointer(true)
111+
}
112+
if g.Starred == nil {
113+
g.Starred = boolPointer(true)
114+
}
115+
if g.JobName == "" {
116+
g.JobName = "GitLab"
117+
}
118+
if g.URL == "" {
119+
g.client, _ = gitlab.NewClient(g.AccessToken)
120+
} else {
121+
client, err := gitlab.NewClient(g.AccessToken, gitlab.WithBaseURL(g.URL))
122+
if err != nil {
123+
panic(err)
124+
}
125+
g.client = client
126+
}
127+
}

go.mod

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,9 @@ module git-backup
33
go 1.17
44

55
require (
6-
github.com/ChappIO/terraform-encrypt v0.0.0-20190529081821-8d96f6eb70d9
76
github.com/go-git/go-git/v5 v5.4.2
87
github.com/google/go-github/v43 v43.0.0
9-
github.com/gorilla/pat v1.0.1
10-
github.com/ian-kent/envconf v0.0.0-20141026121121-c19809918c02
11-
github.com/ian-kent/go-log v0.0.0-20160113211217-5731446c36ab
12-
github.com/influxdata/influxdb v1.9.6
13-
github.com/karalabe/hid v1.0.0
14-
github.com/mailhog/MailHog v1.0.1
15-
github.com/mailhog/MailHog-Server v1.0.1
16-
github.com/mailhog/MailHog-UI v1.0.1
17-
github.com/mailhog/http v1.0.1
18-
github.com/mailhog/mhsendmail v0.2.0
19-
github.com/spf13/cobra v1.4.0
20-
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
8+
github.com/xanzy/go-gitlab v0.60.0
219
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c
2210
gopkg.in/yaml.v2 v2.4.0
2311
)
@@ -26,38 +14,24 @@ require (
2614
github.com/Microsoft/go-winio v0.4.16 // indirect
2715
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
2816
github.com/acomagu/bufpipe v1.0.3 // indirect
29-
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
3017
github.com/emirpasic/gods v1.12.0 // indirect
3118
github.com/go-git/gcfg v1.5.0 // indirect
3219
github.com/go-git/go-billy/v5 v5.3.1 // indirect
3320
github.com/golang/protobuf v1.5.2 // indirect
3421
github.com/google/go-querystring v1.1.0 // indirect
35-
github.com/gorilla/context v1.1.1 // indirect
36-
github.com/gorilla/mux v1.8.0 // indirect
37-
github.com/gorilla/websocket v1.5.0 // indirect
38-
github.com/ian-kent/goose v0.0.0-20141221090059-c3541ea826ad // indirect
39-
github.com/ian-kent/linkio v0.0.0-20170807205755-97566b872887 // indirect
22+
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
23+
github.com/hashicorp/go-retryablehttp v0.6.8 // indirect
4024
github.com/imdario/mergo v0.3.12 // indirect
41-
github.com/inconshreveable/mousetrap v1.0.0 // indirect
4225
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
4326
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
44-
github.com/mailhog/data v1.0.1 // indirect
45-
github.com/mailhog/smtp v1.0.1 // indirect
46-
github.com/mailhog/storage v1.0.1 // indirect
4727
github.com/mitchellh/go-homedir v1.1.0 // indirect
48-
github.com/ogier/pflag v0.0.1 // indirect
49-
github.com/philhofer/fwd v1.0.0 // indirect
5028
github.com/sergi/go-diff v1.1.0 // indirect
51-
github.com/smartystreets/goconvey v1.7.2 // indirect
52-
github.com/spf13/pflag v1.0.5 // indirect
53-
github.com/t-k/fluent-logger-golang v1.0.0 // indirect
54-
github.com/tinylib/msgp v1.1.0 // indirect
5529
github.com/xanzy/ssh-agent v0.3.0 // indirect
30+
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
5631
golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
5732
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
58-
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
33+
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
5934
google.golang.org/appengine v1.6.7 // indirect
6035
google.golang.org/protobuf v1.27.1 // indirect
61-
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
6236
gopkg.in/warnings.v0 v0.1.2 // indirect
6337
)

0 commit comments

Comments
 (0)