Check the `retry-after` header first for rate limit waits. Fall back to `x-ratelimit-remaining` and `x-ratelimit-reset` if necessary, correctly interpreting the reset value as a Unix timestamp. Also simplifies the `ReRequest` helper to use `http.DefaultClient` and refines panic recovery in Gitea asset uploads.
166 lines
5.5 KiB
Go
166 lines
5.5 KiB
Go
package gitea
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"iter"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"net/url"
|
|
"path"
|
|
"strconv"
|
|
|
|
gitea_api "sirherobrine23.com.br/go-bds/request/gitea/structs"
|
|
"sirherobrine23.com.br/go-bds/request/v2"
|
|
)
|
|
|
|
// Get release by tag name
|
|
func (client Gitea) ReleaseTag(tagName string) (*gitea_api.Release, error) {
|
|
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
|
|
client.authHeader(&reqOptions.Header)
|
|
res, _, err := request.JSON[*gitea_api.Release](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases/tags", url.PathEscape(tagName))}).String(), reqOptions)
|
|
return res, err
|
|
}
|
|
|
|
// Get release by ID
|
|
func (client Gitea) Release(id int) (*gitea_api.Release, error) {
|
|
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
|
|
client.authHeader(&reqOptions.Header)
|
|
res, _, err := request.JSON[*gitea_api.Release](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases", strconv.Itoa(id))}).String(), reqOptions)
|
|
return res, err
|
|
}
|
|
|
|
// List all release from gitea APIs
|
|
func (client Gitea) ReleasesSeq() iter.Seq2[*gitea_api.Release, error] {
|
|
releases, res, err := []*gitea_api.Release{}, (*http.Response)(nil), error(nil)
|
|
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
|
|
client.authHeader(&reqOptions.Header)
|
|
return func(yield func(*gitea_api.Release, error) bool) {
|
|
requestUrl := client.Host.ResolveReference(&url.URL{RawQuery: "limit=100", Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases")}).String()
|
|
for requestUrl != "" {
|
|
if len(releases) == 0 {
|
|
if releases, res, err = request.JSON[[]*gitea_api.Release](requestUrl, reqOptions); res != nil {
|
|
requestUrl = parsePaginator(res.Header).NextPageToken
|
|
} else {
|
|
requestUrl = ""
|
|
}
|
|
}
|
|
if err != nil {
|
|
yield(nil, err)
|
|
return
|
|
}
|
|
for len(releases) > 0 {
|
|
if !yield(releases[0], nil) {
|
|
return
|
|
}
|
|
releases = releases[1:]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// List all release Assets in [iter.Seq2]
|
|
func (client Gitea) AssetsSeq(releaseID int) iter.Seq2[*gitea_api.Attachment, error] {
|
|
asserts, res, err := []*gitea_api.Attachment{}, (*http.Response)(nil), error(nil)
|
|
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
|
|
client.authHeader(&reqOptions.Header)
|
|
return func(yield func(*gitea_api.Attachment, error) bool) {
|
|
requestUrl := client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases", strconv.Itoa(releaseID), "assets")}).String()
|
|
for requestUrl != "" {
|
|
if len(asserts) == 0 {
|
|
if asserts, res, err = request.JSON[[]*gitea_api.Attachment](requestUrl, reqOptions); res != nil {
|
|
requestUrl = parsePaginator(res.Header).NextPageToken
|
|
} else {
|
|
requestUrl = ""
|
|
}
|
|
}
|
|
if err != nil {
|
|
yield(nil, err)
|
|
return
|
|
}
|
|
for len(asserts) > 0 {
|
|
if !yield(asserts[0], nil) {
|
|
return
|
|
}
|
|
asserts = asserts[1:]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get all releases from Gitea APIs and return slice with all versions
|
|
func (client Gitea) Releases() ([]*gitea_api.Release, error) {
|
|
releases := []*gitea_api.Release{}
|
|
for release, err := range client.ReleasesSeq() {
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
releases = append(releases, release)
|
|
}
|
|
return releases, nil
|
|
}
|
|
|
|
// List all release Assets in to slice
|
|
func (client Gitea) AllAssets(releaseID int) ([]*gitea_api.Attachment, error) {
|
|
asserts := []*gitea_api.Attachment{}
|
|
for assert, err := range client.AssetsSeq(releaseID) {
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
asserts = append(asserts, assert)
|
|
}
|
|
return asserts, nil
|
|
}
|
|
|
|
// Delete assert file from Release
|
|
func (client Gitea) DeleteAsset(releaseID, assetID int) error {
|
|
reqOptions := &request.Options{Method: "DELETE", Header: request.Header{}, CodeProcess: processCodes}
|
|
client.authHeader(&reqOptions.Header)
|
|
res, err := request.MakeRequestWithStatus(client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases", strconv.Itoa(releaseID), "assets", strconv.Itoa(assetID))}), reqOptions)
|
|
res.Body.Close()
|
|
return err
|
|
}
|
|
|
|
// Upload file to Release
|
|
func (client Gitea) UploadAsset(releaseID int, name string, file io.Reader) (fileInfo *gitea_api.Attachment, err error) {
|
|
defer func(err *error) {
|
|
if err2 := recover(); err2 != nil {
|
|
switch v := err2.(type) {
|
|
case error:
|
|
*err = v
|
|
default:
|
|
*err = fmt.Errorf("%s", err2)
|
|
}
|
|
}
|
|
}(&err)
|
|
readForm, writeForm := io.Pipe()
|
|
mw := multipart.NewWriter(writeForm)
|
|
go func(mw *multipart.Writer) {
|
|
part, err := mw.CreateFormFile("attachment", name)
|
|
if err != nil {
|
|
panic(err)
|
|
} else if _, err = io.Copy(part, file); err != nil {
|
|
panic(err)
|
|
} else if err = mw.Close(); err != nil {
|
|
panic(err)
|
|
}
|
|
}(mw)
|
|
|
|
reqOptions := &request.Options{
|
|
Method: "POST",
|
|
Body: readForm,
|
|
Header: request.Header{
|
|
"Content-Type": mw.FormDataContentType(),
|
|
},
|
|
CodeProcess: processCodes.Extends(request.MapCode{
|
|
201: func(res *http.Response) (*http.Response, error) { return res, nil },
|
|
422: func(res *http.Response) (*http.Response, error) {
|
|
return nil, fmt.Errorf("same filename exists in release: %s", name)
|
|
},
|
|
}),
|
|
}
|
|
client.authHeader(&reqOptions.Header)
|
|
_, err = request.DoJSON(client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases", strconv.Itoa(releaseID), "assets")}).String(), fileInfo, reqOptions)
|
|
return
|
|
}
|