112 lines
2.9 KiB
Go
112 lines
2.9 KiB
Go
|
package repo
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"net/http"
|
||
|
"time"
|
||
|
|
||
|
"code.gitea.io/sdk/gitea"
|
||
|
|
||
|
"git.polynom.me/rio/internal/dns"
|
||
|
)
|
||
|
|
||
|
// Returns true if the repository at <username>/<repository> exists, false if it
|
||
|
// does not.
|
||
|
type GetRepositoryMethod func(username, repositoryName string) (Repository, error)
|
||
|
|
||
|
// Returns <file content>, nil if the file exists at path <path> (relative to the repository) in
|
||
|
// <username>/<repository>@<branch> exists. If not, returns "", error.
|
||
|
type GetFileMethod func(username, repositoryName, branch, path string, since *time.Time) ([]byte, bool, error)
|
||
|
|
||
|
type LookupCNAMEMethod func(domain string) (string, error)
|
||
|
|
||
|
type LookupRepoTXTMethod func(domain string) (string, error)
|
||
|
|
||
|
type HasBranchMethod func(username, repositoryName, branchName string) bool
|
||
|
|
||
|
type HasUserMethod func(username string) bool
|
||
|
|
||
|
type Repository struct {
|
||
|
Name string
|
||
|
}
|
||
|
|
||
|
type GiteaClient struct {
|
||
|
getRepository GetRepositoryMethod
|
||
|
hasBranch HasBranchMethod
|
||
|
hasUser HasUserMethod
|
||
|
GetFile GetFileMethod
|
||
|
lookupCNAME LookupCNAMEMethod
|
||
|
lookupRepoTXT LookupRepoTXTMethod
|
||
|
}
|
||
|
|
||
|
func NewGiteaClient(giteaUrl string, giteaClient *gitea.Client) GiteaClient {
|
||
|
return GiteaClient{
|
||
|
getRepository: func(username, repositoryName string) (Repository, error) {
|
||
|
repo, _, err := giteaClient.GetRepo(username, repositoryName)
|
||
|
if err != nil {
|
||
|
return Repository{}, err
|
||
|
}
|
||
|
|
||
|
return Repository{
|
||
|
Name: repo.Name,
|
||
|
}, nil
|
||
|
},
|
||
|
hasBranch: func(username, repositoryName, branchName string) bool {
|
||
|
res, _, err := giteaClient.ListRepoBranches(username, repositoryName, gitea.ListRepoBranchesOptions{})
|
||
|
if err != nil {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
for _, branch := range res {
|
||
|
if branch.Name == branchName {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
},
|
||
|
hasUser: func(username string) bool {
|
||
|
_, _, err := giteaClient.GetUserInfo(username)
|
||
|
return err == nil
|
||
|
},
|
||
|
GetFile: func(username, repositoryName, branch, path string, since *time.Time) ([]byte, bool, error) {
|
||
|
// We have to do the raw request manually because the Gitea SDK does not allow
|
||
|
// passing the If-Modfied-Since header.
|
||
|
apiUrl := fmt.Sprintf(
|
||
|
"%s/api/v1/repos/%s/%s/raw/%s?ref=%s",
|
||
|
giteaUrl,
|
||
|
username,
|
||
|
repositoryName,
|
||
|
path,
|
||
|
branch,
|
||
|
)
|
||
|
client := &http.Client{}
|
||
|
req, err := http.NewRequest("GET", apiUrl, nil)
|
||
|
if since != nil {
|
||
|
sinceFormat := since.Format(time.RFC1123)
|
||
|
req.Header.Add("If-Modified-Since", sinceFormat)
|
||
|
}
|
||
|
resp, err := client.Do(req)
|
||
|
if err != nil {
|
||
|
return []byte{}, true, err
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
content, err := io.ReadAll(resp.Body)
|
||
|
|
||
|
if err != nil {
|
||
|
return []byte{}, true, err
|
||
|
} else if resp.StatusCode == 302 {
|
||
|
return []byte{}, false, nil
|
||
|
} else {
|
||
|
return content, true, err
|
||
|
}
|
||
|
},
|
||
|
lookupCNAME: func(domain string) (string, error) {
|
||
|
return dns.LookupCNAME(domain)
|
||
|
},
|
||
|
lookupRepoTXT: func(domain string) (string, error) {
|
||
|
return dns.LookupRepoTXT(domain)
|
||
|
},
|
||
|
}
|
||
|
}
|