diff --git a/gitlab/client.go b/gitlab/client.go new file mode 100644 index 0000000..286eda2 --- /dev/null +++ b/gitlab/client.go @@ -0,0 +1,114 @@ +package gitlab + +import ( + "fmt" + + "github.com/xanzy/go-gitlab" +) + +type GroupContentFetcher interface { + FetchGroupContent(path string) (GroupContent, error) +} + +type GroupContent struct { + Repositories []Repository + Groups []Group +} + +type Repository struct { + ID int + Name string + Path string + CloneURL string +} + +type Group struct { + ID int + Name string + Path string +} + +type GitlabClient struct { + Client *gitlab.Client +} + +func NewClient(gitlabUrl string, gitlabToken string) (*GitlabClient, error) { + client, err := gitlab.NewClient( + gitlabToken, + gitlab.WithBaseURL(gitlabUrl), + ) + if err != nil { + return nil, fmt.Errorf("failed to create gitlab client: %w", err) + } + + gitlabClient := &GitlabClient{ + Client: client, + } + return gitlabClient, nil +} + +func NewRepositryFromGitlabProject(project *gitlab.Project) Repository { + // https://godoc.org/github.com/xanzy/go-gitlab#Project + return Repository{ + ID: project.ID, + Name: project.Name, + Path: project.Path, + CloneURL: project.HTTPURLToRepo, + // CloneUrl: project.SSHURLToRepo, + } +} + +func NewGroupFromGitlabGroup(group *gitlab.Group) Group { + // https://godoc.org/github.com/xanzy/go-gitlab#Group + return Group{ + ID: group.ID, + Name: group.Name, + Path: group.Path, + } +} + +func (g GitlabClient) FetchGroupContent(group *Group) (*GroupContent, error) { + content := &GroupContent{} + + // List repositories in path + listProjectOpt := &gitlab.ListGroupProjectsOptions{ + ListOptions: gitlab.ListOptions{ + Page: 1, + }} + for { + projects, response, err := g.Client.Groups.ListGroupProjects(group.ID, listProjectOpt) + if err != nil { + return nil, fmt.Errorf("failed to fetch projects in gitlab: %w", err) + } + for _, project := range projects { + content.Repositories = append(content.Repositories, NewRepositryFromGitlabProject(project)) + } + if response.CurrentPage >= response.TotalPages { + break + } + // Get the next page + listProjectOpt.Page = response.NextPage + } + + // List subgroups in path + ListGroupsOpt := &gitlab.ListSubgroupsOptions{ + ListOptions: gitlab.ListOptions{ + Page: 1, + }} + for { + groups, response, err := g.Client.Groups.ListSubgroups(group.ID, ListGroupsOpt) + if err != nil { + return nil, fmt.Errorf("failed to fetch groups in gitlab: %w", err) + } + for _, group := range groups { + content.Groups = append(content.Groups, NewGroupFromGitlabGroup(group)) + } + if response.CurrentPage >= response.TotalPages { + break + } + // Get the next page + ListGroupsOpt.Page = response.NextPage + } + + return content, nil +} diff --git a/go.mod b/go.mod index 17b1df7..0ad6c06 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/badjware/gitlabfs go 1.15 + +require github.com/xanzy/go-gitlab v0.40.2 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..465f491 --- /dev/null +++ b/go.sum @@ -0,0 +1,28 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-retryablehttp v0.6.4 h1:BbgctKO892xEyOXnGiaAwIoSq1QZ/SS4AhjoAh9DnfY= +github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/xanzy/go-gitlab v0.40.2 h1:XSMIrvcv+7/zK2NPX7Xsa8wC9Qb5vbLfeQ723v4S+qA= +github.com/xanzy/go-gitlab v0.40.2/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181108082009-03003ca0c849 h1:FSqE2GGG7wzsYUsWiQ8MZrvEd1EOyU3NCF0AW3Wtltg= +golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288 h1:JIqe8uIcRBHXDQVvZtHwp80ai3Lw3IJAeJEs55Dc1W0= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index 70a7fe5..56b5e23 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,43 @@ package main -import "fmt" +import ( + "flag" + "fmt" + "os" + + "github.com/badjware/gitlabfs/gitlab" +) func main() { - fmt.Println("Hello world!") + gitlabURL := flag.String("gitlab-url", "https://gitlab.com", "the gitlab url") + gitlabToken := flag.String("gitlab-token", "", "the gitlab authentication token") + gitlabRootGroupID := flag.Int("gitlab-group-id", 9970, "the group id of the groups at the root of the filesystem") + // gitlabNamespace := flag.String() + + flag.Parse() + + gitlabClient, _ := gitlab.NewClient(*gitlabURL, *gitlabToken) + + // TODO: move this + group, _, err := gitlabClient.Client.Groups.GetGroup(*gitlabRootGroupID) + if err != nil { + fmt.Printf("failed to fetch root group with id %v: %w\n", *gitlabRootGroupID, err) + os.Exit(1) + } + rootGroup := gitlab.NewGroupFromGitlabGroup(group) + fmt.Printf("Root group: %v\n", rootGroup.Name) + + content, err := gitlabClient.FetchGroupContent(&rootGroup) + if err != nil { + fmt.Println(err) + } + + fmt.Println("Projects") + for _, r := range content.Repositories { + fmt.Println(r.Name, r.Path, r.CloneURL) + } + fmt.Println("Groups") + for _, g := range content.Groups { + fmt.Println(g.Name, g.Path) + } }