mirror of
https://github.com/cooperspencer/gickup
synced 2025-04-20 05:37:55 +02:00
341 lines
8.1 KiB
Go
341 lines
8.1 KiB
Go
package onedev
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/cooperspencer/gickup/logger"
|
|
"github.com/cooperspencer/gickup/types"
|
|
"github.com/cooperspencer/onedev"
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
var (
|
|
sub zerolog.Logger
|
|
)
|
|
|
|
func Get(conf *types.Conf) ([]types.Repo, bool) {
|
|
ran := false
|
|
repos := []types.Repo{}
|
|
|
|
for _, repo := range conf.Source.OneDev {
|
|
ran = true
|
|
if repo.URL == "" {
|
|
repo.URL = "https://code.onedev.io/"
|
|
}
|
|
sub = logger.CreateSubLogger("stage", "onedev", "url", repo.URL)
|
|
err := repo.Filter.ParseDuration()
|
|
if err != nil {
|
|
sub.Warn().
|
|
Msg(err.Error())
|
|
}
|
|
include := types.GetMap(repo.Include)
|
|
exclude := types.GetMap(repo.Exclude)
|
|
excludeorgs := types.GetMap(repo.ExcludeOrgs)
|
|
|
|
if repo.Password == "" && repo.Token != "" {
|
|
repo.Password = repo.Token
|
|
}
|
|
|
|
client := &onedev.Client{}
|
|
|
|
if repo.Token != "" || repo.TokenFile != "" {
|
|
client = onedev.NewClient(repo.URL, onedev.SetToken(repo.GetToken()))
|
|
} else {
|
|
if repo.Password != "" {
|
|
client = onedev.NewClient(repo.URL, onedev.SetBasicAuth(repo.Username, repo.Password))
|
|
} else {
|
|
client = onedev.NewClient(repo.URL)
|
|
}
|
|
}
|
|
|
|
query := onedev.ProjectQueryOptions{
|
|
Query: "",
|
|
Offset: 0,
|
|
Count: 100,
|
|
}
|
|
|
|
user := onedev.User{}
|
|
|
|
if repo.User == "" {
|
|
u, _, err := client.GetMe()
|
|
if err != nil {
|
|
sub.Error().
|
|
Msg("can't find user")
|
|
break
|
|
}
|
|
user = u
|
|
repo.User = user.Name
|
|
}
|
|
|
|
sub.Info().
|
|
Msgf("grabbing repositories from %s", repo.User)
|
|
|
|
if repo.User != "" {
|
|
query.Query = fmt.Sprintf("owned by \"%s\"", repo.User)
|
|
}
|
|
|
|
userrepos, _, err := client.GetProjects(&query)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msg(err.Error())
|
|
}
|
|
|
|
for _, r := range userrepos {
|
|
urls, _, err := client.GetCloneUrl(r.ID)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msg("couldn't get clone urls")
|
|
continue
|
|
}
|
|
sub.Debug().Msg(urls.HTTP)
|
|
if repo.Filter.ExcludeForks {
|
|
if r.ForkedFromID != 0 {
|
|
continue
|
|
}
|
|
}
|
|
if len(repo.Include) > 0 {
|
|
if !include[r.Name] {
|
|
continue
|
|
}
|
|
if exclude[r.Name] {
|
|
continue
|
|
}
|
|
}
|
|
|
|
defaultbranch, _, err := client.GetDefaultBranch(r.ID)
|
|
if err != nil {
|
|
sub.Warn().
|
|
Msgf("couldn't get default branch for %s", r.Name)
|
|
defaultbranch = "main"
|
|
}
|
|
if defaultbranch == "" {
|
|
continue
|
|
}
|
|
options := onedev.CommitQueryOptions{Query: fmt.Sprintf("branch(%s)", defaultbranch), Fields: []string{onedev.Committer, onedev.Parents, onedev.Author, onedev.CommitDate, onedev.Body, onedev.FileChanges, onedev.LineChanges, onedev.Subject}}
|
|
commits, _, err := client.GetCommits(r.ID, &options)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msgf("can't get latest commit for %s", defaultbranch)
|
|
continue
|
|
}
|
|
|
|
if len(commits) > 0 {
|
|
lastactive := time.UnixMicro(commits[0].Author.When)
|
|
if time.Since(lastactive) > repo.Filter.LastActivityDuration && repo.Filter.LastActivityDuration != 0 {
|
|
continue
|
|
}
|
|
}
|
|
|
|
repos = append(repos, types.Repo{
|
|
Name: r.Name,
|
|
URL: urls.HTTP,
|
|
SSHURL: urls.SSH,
|
|
Token: repo.Token,
|
|
Defaultbranch: defaultbranch,
|
|
Origin: repo,
|
|
Owner: repo.User,
|
|
Hoster: types.GetHost(repo.URL),
|
|
Description: r.Description,
|
|
Issues: GetIssues(&r, client, repo, urls.HTTP),
|
|
})
|
|
}
|
|
|
|
if repo.Username != "" && repo.Password != "" && len(repo.IncludeOrgs) == 0 && user.Name != "" {
|
|
memberships, _, err := client.GetUserMemberships(user.ID)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msgf("couldn't get memberships for %s", user.Name)
|
|
}
|
|
|
|
for _, membership := range memberships {
|
|
group, _, err := client.GetGroup(membership.GroupID)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msgf("couldn't get group with id %d", membership.GroupID)
|
|
}
|
|
if !excludeorgs[group.Name] {
|
|
repo.IncludeOrgs = append(repo.IncludeOrgs, group.Name)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(repo.IncludeOrgs) > 0 {
|
|
for _, org := range repo.IncludeOrgs {
|
|
query.Query = fmt.Sprintf("children of \"%s\"", org)
|
|
|
|
orgrepos, _, err := client.GetProjects(&query)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msg(err.Error())
|
|
}
|
|
|
|
for _, r := range orgrepos {
|
|
if repo.Filter.ExcludeForks {
|
|
if r.ForkedFromID != 0 {
|
|
continue
|
|
}
|
|
}
|
|
urls, _, err := client.GetCloneUrl(r.ID)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msg("couldn't get clone urls")
|
|
continue
|
|
}
|
|
|
|
defaultbranch, _, err := client.GetDefaultBranch(r.ID)
|
|
if err != nil {
|
|
sub.Warn().
|
|
Msgf("couldn't get default branch for %s", r.Name)
|
|
defaultbranch = "main"
|
|
}
|
|
|
|
repos = append(repos, types.Repo{
|
|
Name: r.Name,
|
|
URL: urls.HTTP,
|
|
SSHURL: urls.SSH,
|
|
Token: repo.Token,
|
|
Defaultbranch: defaultbranch,
|
|
Origin: repo,
|
|
Owner: org,
|
|
Hoster: types.GetHost(repo.URL),
|
|
Description: r.Description,
|
|
Issues: GetIssues(&r, client, repo, urls.HTTP),
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return repos, ran
|
|
}
|
|
|
|
func GetOrCreate(destination types.GenRepo, repo types.Repo) (string, error) {
|
|
client := &onedev.Client{}
|
|
if destination.URL == "" {
|
|
destination.URL = "https://code.onedev.io/"
|
|
}
|
|
sub = logger.CreateSubLogger("stage", "onedev", "url", destination.URL)
|
|
|
|
if destination.Token != "" || destination.TokenFile != "" {
|
|
client = onedev.NewClient(destination.URL, onedev.SetToken(destination.GetToken()))
|
|
} else {
|
|
if destination.Password != "" {
|
|
client = onedev.NewClient(destination.URL, onedev.SetBasicAuth(destination.Username, destination.Password))
|
|
} else {
|
|
client = onedev.NewClient(destination.URL, "", "")
|
|
}
|
|
}
|
|
|
|
dest := ""
|
|
|
|
if destination.Organization == "" {
|
|
user, _, err := client.GetMe()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
dest = user.Name
|
|
} else {
|
|
dest = destination.Organization
|
|
}
|
|
|
|
query := onedev.ProjectQueryOptions{
|
|
Query: fmt.Sprintf("\"Name\" is \"%s\" and children of \"%s\"", repo.Name, dest),
|
|
Offset: 0,
|
|
Count: 100,
|
|
}
|
|
projects, _, err := client.GetProjects(&query)
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
for _, project := range projects {
|
|
if project.Name == repo.Name {
|
|
cloneUrls, _, err := client.GetCloneUrl(project.ID)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return cloneUrls.HTTP, nil
|
|
}
|
|
}
|
|
|
|
query.Query = fmt.Sprintf("\"Name\" is \"%s\"", dest)
|
|
|
|
parentid := 0
|
|
parents, _, err := client.GetProjects(&query)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
for _, parent := range parents {
|
|
if parent.Name == dest {
|
|
parentid = parent.ID
|
|
break
|
|
}
|
|
}
|
|
|
|
project, _, err := client.CreateProject(&onedev.CreateProjectOptions{Name: repo.Name, ParentID: parentid, CodeManagement: true})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
cloneUrls, _, err := client.GetCloneUrl(project)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return cloneUrls.HTTP, nil
|
|
}
|
|
|
|
// GetIssues get issues
|
|
func GetIssues(repo *onedev.Project, client *onedev.Client, conf types.GenRepo, repourl string) map[string]interface{} {
|
|
issues := map[string]interface{}{}
|
|
if conf.Issues {
|
|
name := strings.TrimPrefix(repourl, conf.URL)
|
|
listOptions := &onedev.IssueQueryOptions{Count: 100, Offset: 0, Query: fmt.Sprintf("\"Project\" is \"%s\"", name)}
|
|
errorcount := 0
|
|
for {
|
|
i, returncode, err := client.GetIssues(listOptions)
|
|
if err != nil {
|
|
if returncode == http.StatusForbidden {
|
|
sub.Error().Err(err).Str("repo", repo.Name).Msg("can't fetch issues")
|
|
return issues
|
|
}
|
|
if errorcount < 5 {
|
|
sub.Warn().Err(err).Str("repo", repo.Name).Msg("can't fetch issues")
|
|
time.Sleep(5 * time.Second)
|
|
errorcount++
|
|
} else {
|
|
return issues
|
|
}
|
|
} else {
|
|
if len(i) > 0 {
|
|
for _, issue := range i {
|
|
onedevissue := Issue{Issue: issue}
|
|
comments, _, err := client.GetIssueComments(onedevissue.ID)
|
|
if err != nil {
|
|
sub.Error().Err(err).Str("repo", repo.Name).Msg("can't fetch issues")
|
|
} else {
|
|
onedevissue.Comments = comments
|
|
}
|
|
|
|
issues[strconv.Itoa(int(issue.Number))] = onedevissue
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
listOptions.Offset += listOptions.Count
|
|
}
|
|
}
|
|
}
|
|
return issues
|
|
}
|
|
|
|
type Issue struct {
|
|
onedev.Issue
|
|
Comments []onedev.Comment
|
|
}
|