add gitea forge support

This commit is contained in:
Massaki Archambault 2024-08-09 16:13:57 -04:00
parent c8f3de248f
commit 3e84321e85
11 changed files with 472 additions and 11 deletions

View File

@ -7,7 +7,7 @@ fs:
#mountoptions: nodev,nosuid #mountoptions: nodev,nosuid
# The git forge to use as the backend. # The git forge to use as the backend.
# Must be one of "gitlab" or "github" # Must be one of "gitlab", "github", or "gitea"
forge: gitlab forge: gitlab
gitlab: gitlab:
@ -69,6 +69,36 @@ github:
# will be automatically be added to the list of users exposed by the filesystem. # will be automatically be added to the list of users exposed by the filesystem.
include_current_user: true include_current_user: true
gitea:
# The gitea url.
url: https://gitea.com
# The gitlab api token
# Default to anonymous (only public repositories will be visible)
#token:
# Must be set to either "http" or "ssh".
# The protocol to configure the git remote on.
# "http" may not work on private repositories unless a credential manager is configured
# If possible, prefer "ssh" over "http"
pull_method: http
# A list of the name of the organizations to expose in the filesystem
org_names: []
# A list of the name of the user to expose their repositories un the filesystem
user_names: []
# Set how archived repositories are handled.
# If set to "show", it will add them to the filesystem and treat them like any other repository
# If set to "hide", it will add them to the filesystem, but prefix the symlink with a "."
# If set to "ignore", it will make them absent from the filesystem
# Default to "hide"
archived_repo_handling: hide
# If set to true, the personal repositories and the repositories of the organizations the user the api token belongs to
# will be automatically be added to the list of users exposed by the filesystem.
include_current_user: true
git: git:
# Path to the local repository cache. Repositories in the filesystem will symlink to a folder in this path. # Path to the local repository cache. Repositories in the filesystem will symlink to a folder in this path.

View File

@ -24,6 +24,17 @@ github:
archived_repo_handling: hide archived_repo_handling: hide
include_current_user: true include_current_user: true
gitea:
url: https://example.com
token: "12345"
pull_method: http
org_names:
- test-org
user_names:
- test-user
archived_repo_handling: hide
include_current_user: true
git: git:
clone_location: /tmp/gitlabfs/test/cache/gitlab clone_location: /tmp/gitlabfs/test/cache/gitlab
remote: origin remote: origin

View File

@ -11,6 +11,7 @@ import (
const ( const (
ForgeGitlab = "gitlab" ForgeGitlab = "gitlab"
ForgeGithub = "github" ForgeGithub = "github"
ForgeGitea = "gitea"
PullMethodHTTP = "http" PullMethodHTTP = "http"
PullMethodSSH = "ssh" PullMethodSSH = "ssh"
@ -25,6 +26,7 @@ type (
FS FSConfig `yaml:"fs,omitempty"` FS FSConfig `yaml:"fs,omitempty"`
Gitlab GitlabClientConfig `yaml:"gitlab,omitempty"` Gitlab GitlabClientConfig `yaml:"gitlab,omitempty"`
Github GithubClientConfig `yaml:"github,omitempty"` Github GithubClientConfig `yaml:"github,omitempty"`
Gitea GiteaClientConfig `yaml:"gitea,omitempty"`
Git GitClientConfig `yaml:"git,omitempty"` Git GitClientConfig `yaml:"git,omitempty"`
} }
FSConfig struct { FSConfig struct {
@ -53,6 +55,17 @@ type (
IncludeCurrentUser bool `yaml:"include_current_user,omitempty"` IncludeCurrentUser bool `yaml:"include_current_user,omitempty"`
PullMethod string `yaml:"pull_method,omitempty"` PullMethod string `yaml:"pull_method,omitempty"`
} }
GiteaClientConfig struct {
URL string `yaml:"url,omitempty"`
Token string `yaml:"token,omitempty"`
OrgNames []string `yaml:"org_names,omitempty"`
UserNames []string `yaml:"user_names,omitempty"`
ArchivedRepoHandling string `yaml:"archived_repo_handling,omitempty"`
IncludeCurrentUser bool `yaml:"include_current_user,omitempty"`
PullMethod string `yaml:"pull_method,omitempty"`
}
GitClientConfig struct { GitClientConfig struct {
CloneLocation string `yaml:"clone_location,omitempty"` CloneLocation string `yaml:"clone_location,omitempty"`
Remote string `yaml:"remote,omitempty"` Remote string `yaml:"remote,omitempty"`
@ -120,8 +133,8 @@ func LoadConfig(configPath string) (*Config, error) {
} }
// validate forge is set // validate forge is set
if config.FS.Forge != ForgeGithub && config.FS.Forge != ForgeGitlab { if config.FS.Forge != ForgeGithub && config.FS.Forge != ForgeGitlab && config.FS.Forge != ForgeGitea {
return nil, fmt.Errorf("fs.forge must be either \"%v\", or \"%v\"", ForgeGitlab, ForgeGithub) return nil, fmt.Errorf("fs.forge must be either \"%v\", \"%v\", or \"%v\"", ForgeGitlab, ForgeGithub, ForgeGitea)
} }
return config, nil return config, nil
@ -143,18 +156,32 @@ func MakeGitlabConfig(config *Config) (*GitlabClientConfig, error) {
func MakeGithubConfig(config *Config) (*GithubClientConfig, error) { func MakeGithubConfig(config *Config) (*GithubClientConfig, error) {
// parse pull_method // parse pull_method
if config.Gitlab.PullMethod != PullMethodHTTP && config.Gitlab.PullMethod != PullMethodSSH { if config.Github.PullMethod != PullMethodHTTP && config.Github.PullMethod != PullMethodSSH {
return nil, fmt.Errorf("github.pull_method must be either \"%v\" or \"%v\"", PullMethodHTTP, PullMethodSSH) return nil, fmt.Errorf("github.pull_method must be either \"%v\" or \"%v\"", PullMethodHTTP, PullMethodSSH)
} }
// parse archive_handing // parse archive_handing
if config.Gitlab.ArchivedProjectHandling != ArchivedProjectShow && config.Gitlab.ArchivedProjectHandling != ArchivedProjectHide && config.Gitlab.ArchivedProjectHandling != ArchivedProjectIgnore { if config.Github.ArchivedRepoHandling != ArchivedProjectShow && config.Github.ArchivedRepoHandling != ArchivedProjectHide && config.Github.ArchivedRepoHandling != ArchivedProjectIgnore {
return nil, fmt.Errorf("github.archived_repo_handling must be either \"%v\", \"%v\" or \"%v\"", ArchivedProjectShow, ArchivedProjectHide, ArchivedProjectIgnore) return nil, fmt.Errorf("github.archived_repo_handling must be either \"%v\", \"%v\" or \"%v\"", ArchivedProjectShow, ArchivedProjectHide, ArchivedProjectIgnore)
} }
return &config.Github, nil return &config.Github, nil
} }
func MakeGiteaConfig(config *Config) (*GiteaClientConfig, error) {
// parse pull_method
if config.Gitea.PullMethod != PullMethodHTTP && config.Gitea.PullMethod != PullMethodSSH {
return nil, fmt.Errorf("gitea.pull_method must be either \"%v\" or \"%v\"", PullMethodHTTP, PullMethodSSH)
}
// parse archive_handing
if config.Gitea.ArchivedRepoHandling != ArchivedProjectShow && config.Gitea.ArchivedRepoHandling != ArchivedProjectHide && config.Gitea.ArchivedRepoHandling != ArchivedProjectIgnore {
return nil, fmt.Errorf("gitea.archived_repo_handling must be either \"%v\", \"%v\" or \"%v\"", ArchivedProjectShow, ArchivedProjectHide, ArchivedProjectIgnore)
}
return &config.Gitea, nil
}
func MakeGitConfig(config *Config) (*GitClientConfig, error) { func MakeGitConfig(config *Config) (*GitClientConfig, error) {
// parse on_clone // parse on_clone
if config.Git.OnClone != "init" && config.Git.OnClone != "clone" { if config.Git.OnClone != "init" && config.Git.OnClone != "clone" {

View File

@ -37,6 +37,15 @@ func TestLoadConfig(t *testing.T) {
ArchivedRepoHandling: "hide", ArchivedRepoHandling: "hide",
IncludeCurrentUser: true, IncludeCurrentUser: true,
}, },
Gitea: config.GiteaClientConfig{
URL: "https://example.com",
Token: "12345",
PullMethod: "http",
OrgNames: []string{"test-org"},
UserNames: []string{"test-user"},
ArchivedRepoHandling: "hide",
IncludeCurrentUser: true,
},
Git: config.GitClientConfig{ Git: config.GitClientConfig{
CloneLocation: "/tmp/gitlabfs/test/cache/gitlab", CloneLocation: "/tmp/gitlabfs/test/cache/gitlab",
Remote: "origin", Remote: "origin",

96
forges/gitea/client.go Normal file
View File

@ -0,0 +1,96 @@
package gitea
import (
"fmt"
"log/slog"
"sync"
"code.gitea.io/sdk/gitea"
"github.com/badjware/gitlabfs/config"
"github.com/badjware/gitlabfs/fstree"
)
type giteaClient struct {
config.GiteaClientConfig
client *gitea.Client
logger *slog.Logger
rootContent map[string]fstree.GroupSource
// API response cache
organizationCacheMux sync.RWMutex
organizationNameToIDMap map[string]int64
organizationCache map[int64]*Organization
userCacheMux sync.RWMutex
userNameToIDMap map[string]int64
userCache map[int64]*User
}
func NewClient(logger *slog.Logger, config config.GiteaClientConfig) (*giteaClient, error) {
client, err := gitea.NewClient(config.URL, gitea.SetToken(config.Token))
if err != nil {
return nil, fmt.Errorf("failed to create the gitea client: %v", err)
}
giteaClient := &giteaClient{
GiteaClientConfig: config,
client: client,
logger: logger,
rootContent: nil,
organizationNameToIDMap: map[string]int64{},
organizationCache: map[int64]*Organization{},
userNameToIDMap: map[string]int64{},
userCache: map[int64]*User{},
}
// Fetch current user and add it to the list
currentUser, _, err := client.GetMyUserInfo()
if err != nil {
logger.Warn("failed to fetch the current user:", "error", err.Error())
} else {
giteaClient.UserNames = append(giteaClient.UserNames, *&currentUser.UserName)
}
return giteaClient, nil
}
func (c *giteaClient) FetchRootGroupContent() (map[string]fstree.GroupSource, error) {
if c.rootContent == nil {
rootContent := make(map[string]fstree.GroupSource)
for _, orgName := range c.GiteaClientConfig.OrgNames {
org, err := c.fetchOrganization(orgName)
if err != nil {
c.logger.Warn(err.Error())
} else {
rootContent[org.Name] = org
}
}
for _, userName := range c.GiteaClientConfig.UserNames {
user, err := c.fetchUser(userName)
if err != nil {
c.logger.Warn(err.Error())
} else {
rootContent[user.Name] = user
}
}
c.rootContent = rootContent
}
return c.rootContent, nil
}
func (c *giteaClient) FetchGroupContent(gid uint64) (map[string]fstree.GroupSource, map[string]fstree.RepositorySource, error) {
if org, found := c.organizationCache[int64(gid)]; found {
return c.fetchOrganizationContent(org)
}
if user, found := c.userCache[int64(gid)]; found {
return c.fetchUserContent(user)
}
return nil, nil, fmt.Errorf("invalid gid: %v", gid)
}

View File

@ -0,0 +1,104 @@
package gitea
import (
"fmt"
"sync"
"code.gitea.io/sdk/gitea"
"github.com/badjware/gitlabfs/fstree"
)
type Organization struct {
ID int64
Name string
mux sync.Mutex
// hold org content
childRepositories map[string]fstree.RepositorySource
}
func (o *Organization) GetGroupID() uint64 {
return uint64(o.ID)
}
func (o *Organization) InvalidateContentCache() {
o.mux.Lock()
defer o.mux.Unlock()
// clear child repositories from cache
o.childRepositories = nil
}
func (c *giteaClient) fetchOrganization(orgName string) (*Organization, error) {
c.organizationCacheMux.RLock()
cachedId, found := c.organizationNameToIDMap[orgName]
if found {
cachedOrg := c.organizationCache[cachedId]
c.organizationCacheMux.RUnlock()
// if found in cache, return the cached reference
c.logger.Debug("Organization cache hit", "org_name", orgName)
return cachedOrg, nil
} else {
c.organizationCacheMux.RUnlock()
c.logger.Debug("Organization cache miss", "org_name", orgName)
}
// If not found in cache, fetch organization infos from API
giteaOrg, _, err := c.client.GetOrg(orgName)
if err != nil {
return nil, fmt.Errorf("failed to fetch organization with name %v: %v", orgName, err)
}
newOrg := Organization{
ID: giteaOrg.ID,
Name: giteaOrg.UserName,
childRepositories: nil,
}
// save in cache
c.organizationCacheMux.Lock()
c.organizationCache[newOrg.ID] = &newOrg
c.organizationNameToIDMap[newOrg.Name] = newOrg.ID
c.organizationCacheMux.Unlock()
return &newOrg, nil
}
func (c *giteaClient) fetchOrganizationContent(org *Organization) (map[string]fstree.GroupSource, map[string]fstree.RepositorySource, error) {
org.mux.Lock()
defer org.mux.Unlock()
// Get cached data if available
// TODO: cache cache invalidation?
if org.childRepositories == nil {
childRepositories := make(map[string]fstree.RepositorySource)
// Fetch the organization repositories
listReposOptions := gitea.ListReposOptions{
ListOptions: gitea.ListOptions{PageSize: 100},
}
for {
giteaRepositories, response, err := c.client.ListOrgRepos(org.Name, gitea.ListOrgReposOptions(listReposOptions))
if err != nil {
return nil, nil, fmt.Errorf("failed to fetch repository in gitea: %v", err)
}
for _, giteaRepository := range giteaRepositories {
repository := c.newRepositoryFromGiteaRepository(giteaRepository)
if repository != nil {
childRepositories[repository.Path] = repository
}
}
if response.NextPage == 0 {
break
}
// Get the next page
listReposOptions.Page = response.NextPage
}
org.childRepositories = childRepositories
}
return make(map[string]fstree.GroupSource), org.childRepositories, nil
}

View File

@ -0,0 +1,50 @@
package gitea
import (
"path"
"code.gitea.io/sdk/gitea"
"github.com/badjware/gitlabfs/config"
)
type Repository struct {
ID int64
Path string
CloneURL string
DefaultBranch string
}
func (r *Repository) GetRepositoryID() uint64 {
return uint64(r.ID)
}
func (r *Repository) GetCloneURL() string {
return r.CloneURL
}
func (r *Repository) GetDefaultBranch() string {
return r.DefaultBranch
}
func (c *giteaClient) newRepositoryFromGiteaRepository(repository *gitea.Repository) *Repository {
if c.ArchivedRepoHandling == config.ArchivedProjectIgnore && repository.Archived {
return nil
}
r := Repository{
ID: repository.ID,
Path: repository.Name,
DefaultBranch: repository.DefaultBranch,
}
if r.DefaultBranch == "" {
r.DefaultBranch = "master"
}
if c.PullMethod == config.PullMethodSSH {
r.CloneURL = repository.SSHURL
} else {
r.CloneURL = repository.CloneURL
}
if c.ArchivedRepoHandling == config.ArchivedProjectHide && repository.Archived {
r.Path = path.Join(path.Dir(r.Path), "."+path.Base(r.Path))
}
return &r
}

104
forges/gitea/user.go Normal file
View File

@ -0,0 +1,104 @@
package gitea
import (
"fmt"
"sync"
"code.gitea.io/sdk/gitea"
"github.com/badjware/gitlabfs/fstree"
)
type User struct {
ID int64
Name string
mux sync.Mutex
// hold user content
childRepositories map[string]fstree.RepositorySource
}
func (u *User) GetGroupID() uint64 {
return uint64(u.ID)
}
func (u *User) InvalidateContentCache() {
u.mux.Lock()
defer u.mux.Unlock()
// clear child repositories from cache
u.childRepositories = nil
}
func (c *giteaClient) fetchUser(userName string) (*User, error) {
c.userCacheMux.RLock()
cachedId, found := c.userNameToIDMap[userName]
if found {
cachedUser := c.userCache[cachedId]
c.userCacheMux.RUnlock()
// if found in cache, return the cached reference
c.logger.Debug("User cache hit", "user_name", userName)
return cachedUser, nil
} else {
c.userCacheMux.RUnlock()
c.logger.Debug("User cache miss", "user_name", userName)
}
// If not found in cache, fetch user infos from API
giteaUser, _, err := c.client.GetUserInfo(userName)
if err != nil {
return nil, fmt.Errorf("failed to fetch user with name %v: %v", userName, err)
}
newUser := User{
ID: giteaUser.ID,
Name: giteaUser.UserName,
childRepositories: nil,
}
// save in cache
c.userCacheMux.Lock()
c.userCache[newUser.ID] = &newUser
c.userNameToIDMap[newUser.Name] = newUser.ID
c.userCacheMux.Unlock()
return &newUser, nil
}
func (c *giteaClient) fetchUserContent(user *User) (map[string]fstree.GroupSource, map[string]fstree.RepositorySource, error) {
user.mux.Lock()
defer user.mux.Unlock()
// Get cached data if available
// TODO: cache cache invalidation?
if user.childRepositories == nil {
childRepositories := make(map[string]fstree.RepositorySource)
// Fetch the user repositories
listReposOptions := gitea.ListReposOptions{
ListOptions: gitea.ListOptions{PageSize: 100},
}
for {
giteaRepositories, response, err := c.client.ListUserRepos(user.Name, listReposOptions)
if err != nil {
return nil, nil, fmt.Errorf("failed to fetch repository in gitea: %v", err)
}
for _, giteaRepository := range giteaRepositories {
repository := c.newRepositoryFromGiteaRepository(giteaRepository)
if repository != nil {
childRepositories[repository.Path] = repository
}
}
if response.NextPage == 0 {
break
}
// Get the next page
listReposOptions.Page = response.NextPage
}
user.childRepositories = childRepositories
}
return make(map[string]fstree.GroupSource), user.childRepositories, nil
}

9
go.mod
View File

@ -7,14 +7,17 @@ require (
github.com/vmihailenco/taskq/v3 v3.2.9-0.20211122085105-720ffc56ac4d github.com/vmihailenco/taskq/v3 v3.2.9-0.20211122085105-720ffc56ac4d
github.com/xanzy/go-gitlab v0.47.0 github.com/xanzy/go-gitlab v0.47.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
code.gitea.io/sdk/gitea v0.19.0
) )
require ( require (
github.com/bsm/redislock v0.7.2 // indirect github.com/bsm/redislock v0.7.2 // indirect
github.com/capnm/sysinfo v0.0.0-20130621111458-5909a53897f3 // indirect github.com/capnm/sysinfo v0.0.0-20130621111458-5909a53897f3 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davidmz/go-pageant v1.0.2 // indirect
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/go-fed/httpsig v1.1.0 // indirect
github.com/go-redis/redis/v8 v8.11.4 // indirect github.com/go-redis/redis/v8 v8.11.4 // indirect
github.com/go-redis/redis_rate/v9 v9.1.2 // indirect github.com/go-redis/redis_rate/v9 v9.1.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
@ -22,13 +25,15 @@ require (
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.6.8 // indirect github.com/hashicorp/go-retryablehttp v0.6.8 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/klauspost/compress v1.14.4 // indirect github.com/klauspost/compress v1.14.4 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect golang.org/x/crypto v0.22.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 // indirect golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 // indirect
golang.org/x/sys v0.0.0-20210423082822-04245dca01da // indirect golang.org/x/sys v0.19.0 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.26.0 // indirect google.golang.org/protobuf v1.26.0 // indirect

16
go.sum
View File

@ -30,6 +30,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
code.gitea.io/sdk/gitea v0.19.0 h1:8I6s1s4RHgzxiPHhOQdgim1RWIRcr0LVMbHBjBFXq4Y=
code.gitea.io/sdk/gitea v0.19.0/go.mod h1:IG9xZJoltDNeDSW0qiF2Vqx5orMWa7OhVWrjvrd5NpI=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@ -54,6 +56,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
@ -65,6 +69,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -144,6 +150,8 @@ github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrj
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs= github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs=
github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
@ -220,6 +228,9 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -282,9 +293,12 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 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-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/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-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -339,6 +353,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c= golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

17
main.go
View File

@ -8,6 +8,7 @@ import (
"strings" "strings"
"github.com/badjware/gitlabfs/config" "github.com/badjware/gitlabfs/config"
"github.com/badjware/gitlabfs/forges/gitea"
"github.com/badjware/gitlabfs/forges/github" "github.com/badjware/gitlabfs/forges/github"
"github.com/badjware/gitlabfs/forges/gitlab" "github.com/badjware/gitlabfs/forges/gitlab"
"github.com/badjware/gitlabfs/fstree" "github.com/badjware/gitlabfs/fstree"
@ -68,20 +69,28 @@ func main() {
var gitForgeClient fstree.GitForge var gitForgeClient fstree.GitForge
if loadedConfig.FS.Forge == config.ForgeGitlab { if loadedConfig.FS.Forge == config.ForgeGitlab {
// Create the gitlab client // Create the gitlab client
GitlabClientConfig, err := config.MakeGitlabConfig(loadedConfig) gitlabClientConfig, err := config.MakeGitlabConfig(loadedConfig)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
os.Exit(1) os.Exit(1)
} }
gitForgeClient, _ = gitlab.NewClient(logger, *GitlabClientConfig) gitForgeClient, _ = gitlab.NewClient(logger, *gitlabClientConfig)
} else if loadedConfig.FS.Forge == config.ForgeGithub { } else if loadedConfig.FS.Forge == config.ForgeGithub {
// Create the github client // Create the github client
GithubClientConfig, err := config.MakeGithubConfig(loadedConfig) githubClientConfig, err := config.MakeGithubConfig(loadedConfig)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
os.Exit(1) os.Exit(1)
} }
gitForgeClient, _ = github.NewClient(logger, *GithubClientConfig) gitForgeClient, _ = github.NewClient(logger, *githubClientConfig)
} else if loadedConfig.FS.Forge == config.ForgeGitea {
// Create the gitea client
giteaClientConfig, err := config.MakeGiteaConfig(loadedConfig)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
gitForgeClient, _ = gitea.NewClient(logger, *giteaClientConfig)
} }
// Start the filesystem // Start the filesystem