mirror of
https://github.com/cooperspencer/gickup
synced 2024-11-08 12:09:18 +01:00
359 lines
8.1 KiB
Go
359 lines
8.1 KiB
Go
package sourcehut
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/cooperspencer/gickup/logger"
|
|
"github.com/cooperspencer/gickup/types"
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
var (
|
|
sub zerolog.Logger
|
|
)
|
|
|
|
// doRequest TODO
|
|
func doRequest(url, token string) ([]byte, error) {
|
|
req, _ := http.NewRequest("GET", url, nil)
|
|
|
|
req.Header.Add("Authorization", fmt.Sprintf("token %s", token))
|
|
|
|
res, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return []byte{}, err
|
|
}
|
|
|
|
defer res.Body.Close()
|
|
body, err := io.ReadAll(res.Body)
|
|
|
|
return body, err
|
|
}
|
|
|
|
// postRequest TODO
|
|
func postRequest(url string, postbody []byte, token string) ([]byte, error) {
|
|
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(postbody))
|
|
|
|
req.Header.Add("Authorization", fmt.Sprintf("token %s", token))
|
|
req.Header.Add("Content-Type", "application/json")
|
|
|
|
res, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return []byte{}, err
|
|
}
|
|
|
|
defer res.Body.Close()
|
|
body, err := io.ReadAll(res.Body)
|
|
|
|
return body, err
|
|
}
|
|
|
|
// getRepos TODO
|
|
func getRepos(url, token string) (Repositories, error) {
|
|
repositories := Repositories{}
|
|
|
|
body, err := doRequest(url, token)
|
|
if err != nil {
|
|
return Repositories{}, err
|
|
}
|
|
|
|
err = json.Unmarshal(body, &repositories)
|
|
if err != nil {
|
|
return Repositories{}, err
|
|
}
|
|
|
|
for {
|
|
if repositories.Next != "" {
|
|
body, err := doRequest(fmt.Sprintf("%s/id=%s", url, repositories.Next), token)
|
|
if err != nil {
|
|
return Repositories{}, err
|
|
}
|
|
|
|
r := Repositories{}
|
|
|
|
err = json.Unmarshal(body, &r)
|
|
if err != nil {
|
|
return Repositories{}, err
|
|
}
|
|
|
|
repositories.Results = append(repositories.Results, r.Results...)
|
|
repositories.Next = r.Next
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
return repositories, nil
|
|
}
|
|
|
|
// getCommits TODO
|
|
func getCommits(url, reponame, token string) (Commits, error) {
|
|
body, err := doRequest(fmt.Sprintf("%s%s/log", url, reponame), token)
|
|
if err != nil {
|
|
return Commits{}, err
|
|
}
|
|
|
|
commits := Commits{}
|
|
err = json.Unmarshal(body, &commits)
|
|
|
|
return commits, nil
|
|
}
|
|
|
|
// getRefs TODO
|
|
func getRefs(url, name, token string) (Refs, error) {
|
|
body, err := doRequest(fmt.Sprintf("%s%s/refs", url, name), token)
|
|
if err != nil {
|
|
return Refs{}, err
|
|
}
|
|
|
|
refs := Refs{}
|
|
err = json.Unmarshal(body, &refs)
|
|
|
|
for {
|
|
if refs.Next != "" {
|
|
body, err := doRequest(fmt.Sprintf("%s%s/refs/id=%s", url, name, refs.Next), token)
|
|
if err != nil {
|
|
return Refs{}, err
|
|
}
|
|
|
|
r := Refs{}
|
|
|
|
err = json.Unmarshal(body, &r)
|
|
if err != nil {
|
|
return Refs{}, err
|
|
}
|
|
|
|
refs.Results = append(refs.Results, r.Results...)
|
|
refs.Next = r.Next
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
return refs, nil
|
|
}
|
|
|
|
// Get TODO.
|
|
func Get(conf *types.Conf) ([]types.Repo, bool) {
|
|
ran := false
|
|
repos := []types.Repo{}
|
|
for _, repo := range conf.Source.Sourcehut {
|
|
if repo.URL == "" {
|
|
repo.URL = "https://git.sr.ht"
|
|
}
|
|
|
|
if !strings.HasSuffix(repo.URL, "/") {
|
|
repo.URL += "/"
|
|
}
|
|
|
|
sub = logger.CreateSubLogger("stage", "sourcehut", "url", repo.URL)
|
|
err := repo.Filter.ParseDuration()
|
|
if err != nil {
|
|
sub.Error().
|
|
Msg(err.Error())
|
|
}
|
|
ran = true
|
|
|
|
apiURL := fmt.Sprintf("%sapi/", repo.URL)
|
|
|
|
token := repo.GetToken()
|
|
|
|
if repo.User == "" {
|
|
user := User{}
|
|
body, err := doRequest(fmt.Sprintf("%suser", apiURL), token)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msg("no user associated with this token")
|
|
continue
|
|
}
|
|
|
|
err = json.Unmarshal(body, &user)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msg("cannot unmarshal user")
|
|
continue
|
|
}
|
|
repo.User = user.Name
|
|
}
|
|
|
|
sub.Info().
|
|
Msgf("grabbing repositories from %s", repo.User)
|
|
|
|
if repo.User != "" {
|
|
if !strings.HasPrefix(repo.User, "~") {
|
|
repo.User = fmt.Sprintf("~%s", repo.User)
|
|
}
|
|
}
|
|
|
|
apiURL = fmt.Sprintf("%sapi/%s/repos/", repo.URL, repo.User)
|
|
|
|
include := types.GetMap(repo.Include)
|
|
exclude := types.GetMap(repo.Exclude)
|
|
|
|
repositories, err := getRepos(apiURL, token)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msg(err.Error())
|
|
}
|
|
|
|
for _, r := range repositories.Results {
|
|
repoURL := fmt.Sprintf("%s%s/%s", repo.URL, repo.User, r.Name)
|
|
sshURL := fmt.Sprintf("git@%s:%s/%s", types.GetHost(repo.URL), r.Owner.CanonicalName, r.Name)
|
|
sub.Debug().Msg(repoURL)
|
|
|
|
refs, err := getRefs(apiURL, r.Name, token)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msg(err.Error())
|
|
}
|
|
|
|
head := ""
|
|
for _, ref := range refs.Results {
|
|
if strings.HasPrefix("refs/heads/", ref.Name) {
|
|
head = strings.TrimLeft(ref.Name, "refs/heads/")
|
|
break
|
|
}
|
|
}
|
|
|
|
commits, err := getCommits(apiURL, r.Name, token)
|
|
if err != nil {
|
|
sub.Error().
|
|
Msg(err.Error())
|
|
} else {
|
|
if len(commits.Results) > 0 {
|
|
if time.Since(commits.Results[0].Timestamp) > repo.Filter.LastActivityDuration && repo.Filter.LastActivityDuration != 0 {
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
if include[r.Name] {
|
|
repos = append(repos, types.Repo{
|
|
Name: r.Name,
|
|
URL: repoURL,
|
|
SSHURL: sshURL,
|
|
Token: token,
|
|
Defaultbranch: refs.Results[0].Name,
|
|
Origin: repo,
|
|
Owner: r.Owner.Name,
|
|
Hoster: types.GetHost(repo.URL),
|
|
Description: r.Description,
|
|
Private: r.Visibility == "private",
|
|
})
|
|
if repo.Wiki {
|
|
repos = append(repos, types.Repo{
|
|
Name: r.Name + ".-docs",
|
|
URL: repoURL + "-docs",
|
|
SSHURL: sshURL + "-docs",
|
|
Token: token,
|
|
Defaultbranch: head,
|
|
Origin: repo,
|
|
Owner: r.Owner.Name,
|
|
Hoster: types.GetHost(repo.URL),
|
|
Description: r.Description,
|
|
Private: r.Visibility == "private",
|
|
})
|
|
}
|
|
|
|
continue
|
|
}
|
|
|
|
if exclude[r.Name] {
|
|
continue
|
|
}
|
|
|
|
if len(include) == 0 {
|
|
repos = append(repos, types.Repo{
|
|
Name: r.Name,
|
|
URL: repoURL,
|
|
SSHURL: sshURL,
|
|
Token: token,
|
|
Defaultbranch: head,
|
|
Origin: repo,
|
|
Owner: r.Owner.Name,
|
|
Hoster: types.GetHost(repo.URL),
|
|
Description: r.Description,
|
|
Private: r.Visibility == "private",
|
|
})
|
|
if repo.Wiki {
|
|
refs, err := getRefs(apiURL, fmt.Sprintf("%s-docs", r.Name), token)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if len(refs.Results) > 0 {
|
|
head = ""
|
|
for _, ref := range refs.Results {
|
|
if strings.HasPrefix("refs/heads/", ref.Name) {
|
|
head = strings.TrimLeft(ref.Name, "refs/heads/")
|
|
break
|
|
}
|
|
}
|
|
|
|
repos = append(repos, types.Repo{
|
|
Name: r.Name + "-docs",
|
|
URL: repoURL + "-docs",
|
|
SSHURL: sshURL + "-docs",
|
|
Token: token,
|
|
Defaultbranch: head,
|
|
Origin: repo,
|
|
Owner: r.Owner.Name,
|
|
Hoster: types.GetHost(repo.URL),
|
|
Description: r.Description,
|
|
Private: r.Visibility == "private",
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return repos, ran
|
|
}
|
|
|
|
func GetOrCreate(destination types.GenRepo, repo types.Repo) (string, error) {
|
|
if destination.URL == "" {
|
|
destination.URL = "https://git.sr.ht"
|
|
}
|
|
|
|
sub = logger.CreateSubLogger("stage", "sourcehut", "url", destination.URL)
|
|
|
|
if !strings.HasSuffix(destination.URL, "/") {
|
|
destination.URL += "/"
|
|
}
|
|
|
|
repository := Repository{}
|
|
body, err := doRequest(fmt.Sprintf("%sapi/repos/%s", destination.URL, repo.Name), destination.GetToken())
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
err = json.Unmarshal(body, &repository)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if repository.Name == "" {
|
|
if destination.Visibility.Repositories != "public" && destination.Visibility.Repositories != "private" && destination.Visibility.Repositories != "unlisted" {
|
|
destination.Visibility.Repositories = "public"
|
|
}
|
|
postRepo := PostRepo{Name: repo.Name, Visibility: destination.Visibility.Repositories}
|
|
postBody, err := json.Marshal(postRepo)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
body, err := postRequest(fmt.Sprintf("%sapi/repos", destination.URL), postBody, destination.GetToken())
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
err = json.Unmarshal(body, &repository)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
return fmt.Sprintf("git@%s:%s/%s", types.GetHost(destination.URL), repository.Owner.CanonicalName, repo.Name), nil
|
|
}
|