package gitlabremote import ( "time" "github.com/pterm/pterm" "github.com/xanzy/go-gitlab" "gitea.libretechconsulting.com/rmcguire/git-project-manager/internal/remotes/info" "gitea.libretechconsulting.com/rmcguire/git-project-manager/internal/remotes/projects" "gitea.libretechconsulting.com/rmcguire/git-project-manager/internal/remotes/remote" ) var DefaultListOpts = &gitlab.ListProjectsOptions{ ListOptions: gitlab.ListOptions{ PerPage: projectsPerPage, Page: 1, }, Archived: gitlab.Ptr[bool](false), } var ( defApiWaitMin time.Duration = 2 * time.Second defApiWaitMax time.Duration = 5 * time.Second ) func NewGitlabApi(remoteInfo *info.RemoteInfo) (*gitlab.Client, error) { client, err := gitlab.NewClient( remoteInfo.Token, gitlab.WithBaseURL(remoteInfo.Host), gitlab.WithCustomRetryWaitMinMax(defApiWaitMin, defApiWaitMax), ) if err != nil { return nil, err } return client, nil } func (r *GitlabRemote) GetNumProjects(opts *remote.RemoteQueryOpts) int { listOpts := *DefaultListOpts listOpts.PerPage = 1 listOpts.Page = 1 listOpts.Simple = gitlab.Ptr[bool](true) _, resp, err := r.api.Projects.ListProjects(&listOpts, r.GetDefaultRequestOptions()...) if err != nil { pterm.Error.Printfln("Failed getting number of GitLab projects: %s", err) return -1 } return resp.TotalItems } // Returns a list of projects along with the next page and an error // if there was an error func (r *GitlabRemote) ListProjects(opts *gitlab.ListProjectsOptions) ( []*projects.Project, *gitlab.Response, error) { pList := make([]*projects.Project, 0) projects, resp, err := r.api.Projects.ListProjects( opts, r.GetDefaultRequestOptions()..., ) if err == nil { pList = append(pList, r.handleProjects(projects)...) } return pList, resp, err } func (r *GitlabRemote) handleProjects(gitProjects []*gitlab.Project) []*projects.Project { // Opportunity to perform any filtering or additional lookups // on a per-project basis pList := make([]*projects.Project, 0, len(gitProjects)) for _, project := range gitProjects { var owner string if project.Owner != nil { owner = project.Owner.Email } p := &projects.Project{ ID: project.ID, Description: project.Description, SSHURLToRepo: project.SSHURLToRepo, HTTPURLToRepo: project.HTTPURLToRepo, WebURL: project.WebURL, Name: project.Name, NameWithNamespace: project.NameWithNamespace, Path: project.Path, PathWithNamespace: project.PathWithNamespace, Remote: r.info.Host, Owner: owner, AvatarURL: project.AvatarURL, LastActivityAt: *project.LastActivityAt, Readme: project.ReadmeURL, Languages: r.GetProjectLanguages(project), } pList = append(pList, p) } return pList } // A nil return indicates an API error or GitLab doesn't know what // language the project uses. func (r *GitlabRemote) GetProjectLanguages(project *gitlab.Project) *projects.ProjectLanguages { l, _, e := r.api.Projects.GetProjectLanguages(project.ID, r.GetDefaultRequestOptions()...) if e != nil { pterm.Error.Printfln("Failed requesting project languages: %s", e.Error()) return nil } var pLangs projects.ProjectLanguages pLangs = make([]*projects.ProjectLanguage, len(*l)) var i int for name, pcnt := range *l { pLangs[i] = &projects.ProjectLanguage{ Name: name, Percentage: pcnt, } i++ } return &pLangs } func (r *GitlabRemote) GetDefaultRequestOptions() []gitlab.RequestOptionFunc { requestOpts := make([]gitlab.RequestOptionFunc, 1) requestOpts[0] = gitlab.WithContext(r.GetInfo().Context()) return requestOpts }