From 3e84321e85d591519651b4226be48ce5f152b5c2 Mon Sep 17 00:00:00 2001 From: Massaki Archambault Date: Fri, 9 Aug 2024 16:13:57 -0400 Subject: [PATCH] add gitea forge support --- config.example.yaml | 32 ++++++++++- config/config.test.yaml | 11 ++++ config/loader.go | 35 ++++++++++-- config/loader_test.go | 9 +++ forges/gitea/client.go | 96 ++++++++++++++++++++++++++++++++ forges/gitea/organization.go | 104 +++++++++++++++++++++++++++++++++++ forges/gitea/repository.go | 50 +++++++++++++++++ forges/gitea/user.go | 104 +++++++++++++++++++++++++++++++++++ go.mod | 9 ++- go.sum | 16 ++++++ main.go | 17 ++++-- 11 files changed, 472 insertions(+), 11 deletions(-) create mode 100644 forges/gitea/client.go create mode 100644 forges/gitea/organization.go create mode 100644 forges/gitea/repository.go create mode 100644 forges/gitea/user.go diff --git a/config.example.yaml b/config.example.yaml index 4dbfb1a..74591a9 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -7,7 +7,7 @@ fs: #mountoptions: nodev,nosuid # 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 gitlab: @@ -69,6 +69,36 @@ github: # will be automatically be added to the list of users exposed by the filesystem. 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: # Path to the local repository cache. Repositories in the filesystem will symlink to a folder in this path. diff --git a/config/config.test.yaml b/config/config.test.yaml index 637c992..fc28230 100644 --- a/config/config.test.yaml +++ b/config/config.test.yaml @@ -24,6 +24,17 @@ github: archived_repo_handling: hide 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: clone_location: /tmp/gitlabfs/test/cache/gitlab remote: origin diff --git a/config/loader.go b/config/loader.go index b785f7b..ca955b6 100644 --- a/config/loader.go +++ b/config/loader.go @@ -11,6 +11,7 @@ import ( const ( ForgeGitlab = "gitlab" ForgeGithub = "github" + ForgeGitea = "gitea" PullMethodHTTP = "http" PullMethodSSH = "ssh" @@ -25,6 +26,7 @@ type ( FS FSConfig `yaml:"fs,omitempty"` Gitlab GitlabClientConfig `yaml:"gitlab,omitempty"` Github GithubClientConfig `yaml:"github,omitempty"` + Gitea GiteaClientConfig `yaml:"gitea,omitempty"` Git GitClientConfig `yaml:"git,omitempty"` } FSConfig struct { @@ -53,6 +55,17 @@ type ( IncludeCurrentUser bool `yaml:"include_current_user,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 { CloneLocation string `yaml:"clone_location,omitempty"` Remote string `yaml:"remote,omitempty"` @@ -120,8 +133,8 @@ func LoadConfig(configPath string) (*Config, error) { } // validate forge is set - if config.FS.Forge != ForgeGithub && config.FS.Forge != ForgeGitlab { - return nil, fmt.Errorf("fs.forge must be either \"%v\", or \"%v\"", ForgeGitlab, ForgeGithub) + if config.FS.Forge != ForgeGithub && config.FS.Forge != ForgeGitlab && config.FS.Forge != ForgeGitea { + return nil, fmt.Errorf("fs.forge must be either \"%v\", \"%v\", or \"%v\"", ForgeGitlab, ForgeGithub, ForgeGitea) } return config, nil @@ -143,18 +156,32 @@ func MakeGitlabConfig(config *Config) (*GitlabClientConfig, error) { func MakeGithubConfig(config *Config) (*GithubClientConfig, error) { // 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) } // 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 &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) { // parse on_clone if config.Git.OnClone != "init" && config.Git.OnClone != "clone" { diff --git a/config/loader_test.go b/config/loader_test.go index 8aa3821..421a0db 100644 --- a/config/loader_test.go +++ b/config/loader_test.go @@ -37,6 +37,15 @@ func TestLoadConfig(t *testing.T) { ArchivedRepoHandling: "hide", 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{ CloneLocation: "/tmp/gitlabfs/test/cache/gitlab", Remote: "origin", diff --git a/forges/gitea/client.go b/forges/gitea/client.go new file mode 100644 index 0000000..b158786 --- /dev/null +++ b/forges/gitea/client.go @@ -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, *¤tUser.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) +} diff --git a/forges/gitea/organization.go b/forges/gitea/organization.go new file mode 100644 index 0000000..5b527a0 --- /dev/null +++ b/forges/gitea/organization.go @@ -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 +} diff --git a/forges/gitea/repository.go b/forges/gitea/repository.go new file mode 100644 index 0000000..9ae4529 --- /dev/null +++ b/forges/gitea/repository.go @@ -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 +} diff --git a/forges/gitea/user.go b/forges/gitea/user.go new file mode 100644 index 0000000..a8079ec --- /dev/null +++ b/forges/gitea/user.go @@ -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 +} diff --git a/go.mod b/go.mod index 358f256..4cab85f 100644 --- a/go.mod +++ b/go.mod @@ -7,14 +7,17 @@ require ( github.com/vmihailenco/taskq/v3 v3.2.9-0.20211122085105-720ffc56ac4d github.com/xanzy/go-gitlab v0.47.0 gopkg.in/yaml.v2 v2.4.0 + code.gitea.io/sdk/gitea v0.19.0 ) require ( github.com/bsm/redislock v0.7.2 // indirect github.com/capnm/sysinfo v0.0.0-20130621111458-5909a53897f3 // 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-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_rate/v9 v9.1.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/hashicorp/go-cleanhttp v0.5.2 // 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/klauspost/compress v1.14.4 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // 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/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 google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.26.0 // indirect diff --git a/go.sum b/go.sum index b3a093a..b643cc8 100644 --- a/go.sum +++ b/go.sum @@ -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.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= 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= 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= @@ -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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 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/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= 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.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 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/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= @@ -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.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs= 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.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 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-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-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-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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-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-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-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= 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-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c= 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/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= diff --git a/main.go b/main.go index 83fb40c..9b2fdf2 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/badjware/gitlabfs/config" + "github.com/badjware/gitlabfs/forges/gitea" "github.com/badjware/gitlabfs/forges/github" "github.com/badjware/gitlabfs/forges/gitlab" "github.com/badjware/gitlabfs/fstree" @@ -68,20 +69,28 @@ func main() { var gitForgeClient fstree.GitForge if loadedConfig.FS.Forge == config.ForgeGitlab { // Create the gitlab client - GitlabClientConfig, err := config.MakeGitlabConfig(loadedConfig) + gitlabClientConfig, err := config.MakeGitlabConfig(loadedConfig) if err != nil { fmt.Println(err) os.Exit(1) } - gitForgeClient, _ = gitlab.NewClient(logger, *GitlabClientConfig) + gitForgeClient, _ = gitlab.NewClient(logger, *gitlabClientConfig) } else if loadedConfig.FS.Forge == config.ForgeGithub { // Create the github client - GithubClientConfig, err := config.MakeGithubConfig(loadedConfig) + githubClientConfig, err := config.MakeGithubConfig(loadedConfig) if err != nil { fmt.Println(err) 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