134 lines
3.6 KiB
Go
134 lines
3.6 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/base64"
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
type Storage interface {
|
||
|
CreateFile(path string, file string, message string) (err error)
|
||
|
UpdateFile(path string, file string, message string) (err error)
|
||
|
ReadFile(path string) (content string, sha string, exists bool, err error)
|
||
|
}
|
||
|
|
||
|
// Gitea
|
||
|
type Gitea struct {
|
||
|
endpoint string
|
||
|
token string
|
||
|
}
|
||
|
|
||
|
type giteaCommitRequest struct {
|
||
|
Content string `json:"content"`
|
||
|
Message string `json:"message"`
|
||
|
SHA string `json:"sha,omitempty"`
|
||
|
}
|
||
|
|
||
|
type giteaReadResponse struct {
|
||
|
Type string `json:"type"`
|
||
|
Content string `json:"content"`
|
||
|
SHA string `json:"sha"`
|
||
|
}
|
||
|
|
||
|
type giteaErrorResponse struct {
|
||
|
Message string `json:"message"`
|
||
|
}
|
||
|
|
||
|
func (gitea *Gitea) CreateFile(path string, file string, message string) (err error) {
|
||
|
request := &giteaCommitRequest{
|
||
|
Content: base64.StdEncoding.EncodeToString([]byte(file)),
|
||
|
Message: message,
|
||
|
}
|
||
|
bytesRepresentation, err := json.Marshal(request)
|
||
|
if err != nil {
|
||
|
return errors.New("failed to marshal json before committing")
|
||
|
}
|
||
|
resp, err := http.Post(gitea.endpoint+url.QueryEscape(path)+"?access_token="+gitea.token, "application/json", bytes.NewBuffer(bytesRepresentation))
|
||
|
if err != nil || resp.StatusCode != 201 {
|
||
|
return errors.New("failed to create file in repo")
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (gitea *Gitea) UpdateFile(path string, file string, message string) (err error) {
|
||
|
_, sha, exists, err := gitea.ReadFile(path)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if !exists {
|
||
|
// File doesn't exist, create it
|
||
|
return gitea.CreateFile(path, file, message)
|
||
|
}
|
||
|
request := &giteaCommitRequest{
|
||
|
Content: base64.StdEncoding.EncodeToString([]byte(file)),
|
||
|
Message: message,
|
||
|
SHA: sha,
|
||
|
}
|
||
|
bytesRepresentation, err := json.Marshal(request)
|
||
|
if err != nil {
|
||
|
return errors.New("failed to marshal json before committing")
|
||
|
}
|
||
|
req, err := http.NewRequest(http.MethodPut, gitea.endpoint+url.QueryEscape(path)+"?access_token="+gitea.token, bytes.NewBuffer(bytesRepresentation))
|
||
|
if err != nil {
|
||
|
return errors.New("error making update request")
|
||
|
}
|
||
|
req.Header.Set("Content-type", "application/json")
|
||
|
client := &http.Client{}
|
||
|
resp, err := client.Do(req)
|
||
|
if err != nil || resp.StatusCode != 200 {
|
||
|
return errors.New("failed to update file in repo")
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (gitea *Gitea) ReadFile(path string) (content string, sha string, exists bool, err error) {
|
||
|
exists = false
|
||
|
resp, err := http.Get(gitea.endpoint + url.QueryEscape(path) + "?access_token=" + gitea.token)
|
||
|
if err != nil || resp.StatusCode != 200 {
|
||
|
if resp != nil {
|
||
|
defer resp.Body.Close()
|
||
|
body, readErr := ioutil.ReadAll(resp.Body)
|
||
|
if readErr != nil {
|
||
|
err = errors.New("failed reading Gitea error response")
|
||
|
return
|
||
|
}
|
||
|
errorResponse := &giteaErrorResponse{}
|
||
|
marshalErr := json.Unmarshal(body, &errorResponse)
|
||
|
if marshalErr != nil {
|
||
|
err = errors.New("failed parsing Gitea error response")
|
||
|
return
|
||
|
}
|
||
|
exists = !strings.Contains(errorResponse.Message, "does not exist")
|
||
|
if !exists {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
err = errors.New("failed to read file in repo")
|
||
|
return
|
||
|
}
|
||
|
exists = true
|
||
|
defer resp.Body.Close()
|
||
|
body, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
err = errors.New("failed reading file in repo")
|
||
|
return
|
||
|
}
|
||
|
readResponse := &giteaReadResponse{}
|
||
|
err = json.Unmarshal(body, &readResponse)
|
||
|
if err != nil {
|
||
|
err = errors.New("failed parsing Gitea response")
|
||
|
return
|
||
|
}
|
||
|
decodedContentBytes, err := base64.StdEncoding.DecodeString(readResponse.Content)
|
||
|
if err != nil {
|
||
|
err = errors.New("failed decoding file content")
|
||
|
}
|
||
|
content = string(decodedContentBytes)
|
||
|
sha = readResponse.SHA
|
||
|
return
|
||
|
}
|