rio/repo.go

133 lines
2.9 KiB
Go

package main
import (
"errors"
"strings"
"time"
"code.gitea.io/sdk/gitea"
"github.com/patrickmn/go-cache"
log "github.com/sirupsen/logrus"
)
var (
pathCache = cache.New(1 * time.Hour, 1 * time.Hour)
)
type PageCacheEntry struct {
Repository *gitea.Repository
Path string
}
func makePageCacheKey(domain, path string) string {
return domain + "/" + path
}
/// Try to find the repository with name @reponame of the user @username. If @cname
/// is not "", then it also verifies that the repository contains a "CNAME" with
/// the value of @cname as its content. @host, @domain, and @path are passed for
/// caching on success.
func lookupRepositoryAndCache(username, reponame, host, domain, path, cname string, giteaClient *gitea.Client) (*gitea.Repository, error) {
log.Debugf("Looking up repository %s/%s", username, reponame)
repo, _, err := giteaClient.GetRepo(username, reponame)
if err != nil {
return nil, err
}
// Check if the CNAME file matches
if cname != "" {
file, _, err := giteaClient.GetFile(
username,
repo.Name,
PagesBranch,
"CNAME",
false,
)
if err != nil {
log.Errorf("Could not verify CNAME of %s/%s: %v\n", username, repo.Name, err)
return nil, err
}
cnameContent := strings.Trim(
string(file[:]),
"\n",
)
if cnameContent != cname {
return nil, errors.New("CNAME mismatch")
}
}
// Cache data
pathCache.Set(
makePageCacheKey(domain, path),
PageCacheEntry{
repo,
path,
},
cache.DefaultExpiration,
)
return repo, nil
}
func RepoFromPath(username, host, cname, path string, giteaClient *gitea.Client) (*gitea.Repository, string, error) {
domain := host
// Guess the repository
key := makePageCacheKey(domain, path)
entry, found := pathCache.Get(key)
if found {
pageEntry := entry.(PageCacheEntry)
return pageEntry.Repository, pageEntry.Path, nil
}
pathParts := strings.Split(path, "/")
if len(pathParts) > 1 {
log.Debugf("Trying repository %s", pathParts[0])
modifiedPath := strings.Join(pathParts[1:], "/")
repo, err := lookupRepositoryAndCache(
username,
pathParts[0],
host,
domain,
modifiedPath,
cname,
giteaClient,
)
if err == nil {
return repo, modifiedPath, nil
}
}
// Allow specifying the repository name in the TXT record
reponame := domain
lookupDomain := domain
if cname != "" {
lookupDomain = cname
}
repoLookup, err := lookupRepoTXT(lookupDomain)
if err != nil && repoLookup != "" {
log.Infof(
"TXT lookup for %s resulted in choosing repository %s",
lookupDomain,
repoLookup,
)
reponame = repoLookup
} else if (cname != "") {
// Allow naming the repository "example.org" (But give the TXT record preference)
reponame = cname;
}
log.Debugf("Trying repository %s/%s", username, reponame)
repo, err := lookupRepositoryAndCache(
username,
reponame,
host,
domain,
path,
cname,
giteaClient,
)
return repo, path, err
}