autogits/bots-common/obs_utils.go
2024-07-26 16:53:09 +02:00

252 lines
5.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package common
import (
"bytes"
"encoding/xml"
"fmt"
"io"
"log"
"net/http"
"net/url"
)
type ObsClient struct {
baseUrl *url.URL
client *http.Client
user, password string
cookie string
HomeProject string
}
func NewObsClient(host string) (*ObsClient, error) {
baseUrl, err := url.Parse("https://" + host)
if err != nil {
return nil, err
}
return &ObsClient{
baseUrl: baseUrl,
client: &http.Client{},
user: obsUser,
password: obsPassword,
HomeProject: fmt.Sprintf("home:%s", obsUser),
}, nil
}
type RepositoryPathMeta struct {
Project string `xml:"project,attr"`
Repository string `xml:"repository,attr"`
}
type RepositoryMeta struct {
Name string `xml:"name,attr"`
Archs []string `xml:"arch"`
Paths []RepositoryPathMeta `xml:"path"`
}
type Flags struct {
Contents string `xml:",innerxml"`
}
type ProjectMeta struct {
XMLName xml.Name `xml:"project"`
Name string `xml:"name,attr"`
Title string `xml:"title"`
Description string `xml:"description"`
ScmSync string `xml:"scmsync"`
Repositories []RepositoryMeta `xml:"repository"`
BuildFlags Flags `xml:"build"`
PublicFlags Flags `xml:"publish"`
DebugFlags Flags `xml:"debuginfo"`
UseForBuild Flags `xml:"useforbuild"`
}
func parseProjectMeta(data []byte) (*ProjectMeta, error) {
var meta ProjectMeta
err := xml.Unmarshal(data, &meta)
if err != nil {
return nil, err
}
return &meta, nil
}
func (c *ObsClient) GetProjectMeta(project string) (*ProjectMeta, error) {
req, err := http.NewRequest("GET", c.baseUrl.JoinPath("source", project, "_meta").String(), nil)
if err != nil {
return nil, err
}
req.SetBasicAuth(c.user, c.password)
log.Printf("request: %#v", *req.URL)
log.Printf("headers: %#v", req.Header)
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
switch res.StatusCode {
case 200:
break
case 404:
return nil, nil
default:
return nil, fmt.Errorf("Unexpected return code: %d", res.StatusCode)
}
data, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
return parseProjectMeta(data)
}
func ObsSafeProjectName(prjname string) string {
if len(prjname) < 1 {
return prjname
} else if len(prjname) > 200 {
prjname = prjname[:199]
}
switch prjname[0] {
case '_', '.', ':':
prjname = "X" + prjname[1:]
// no UTF-8 in OBS :(
// prjname = "_" + prjname[1:]
// case ':':
// prjname = "" + prjname[1:]
// case '.':
// prjname = "" + prjname[1:]
}
return prjname
}
func (c *ObsClient) SetProjectMeta(meta *ProjectMeta) (error) {
req, err := http.NewRequest("PUT", c.baseUrl.JoinPath("source", meta.Name, "_meta").String(), nil)
if err != nil {
return err
}
req.SetBasicAuth(c.user, c.password)
xml, err := xml.Marshal(meta)
if err != nil {
return err
}
req.Body = io.NopCloser(bytes.NewReader(xml))
log.Printf("headers: %#v", req.Header)
log.Printf("xml: %s", xml)
res, err := c.client.Do(req)
if err != nil {
return err
}
switch res.StatusCode {
case 200:
break
default:
return fmt.Errorf("Unexpected return code: %d", res.StatusCode)
}
return nil
}
func (c *ObsClient) DeleteProject(project string) error {
req, err := http.NewRequest("DELETE", c.baseUrl.JoinPath("source", project).String(), nil)
if err != nil {
return err
}
req.SetBasicAuth(c.user, c.password)
res, err := c.client.Do(req)
if err != nil {
return err
}
if res.StatusCode != 200 {
return fmt.Errorf("Unexpected return code: %d", res.StatusCode)
}
return nil
}
type BuildStatus struct {
Package string `xml:"package,attr"`
Code string `xml:"code,attr"`
Details string `xml:"details"`
}
type BuildResult struct {
Project string `xml:"project,attr"`
Repository string `xml:"repository,attr"`
Arch string `xml:"arch,attr"`
Code string `xml:"code,attr"`
Status []BuildStatus `xml:"status"`
Binaries []BinaryList `xml:"binarylist"`
}
type Binary struct {
Size uint64 `xml:"size,attr"`
Filename string `xml:"filename,attr"`
Mtime uint64 `xml:"mtime,attr"`
}
type BinaryList struct {
Package string `xml:"package,attr"`
Binary []Binary `xml:"binary"`
}
type BuildResultList struct {
XMLName xml.Name `xml:"resultlist"`
Result []BuildResult `xml:"result"`
}
func parseBuildResults(data []byte) (*BuildResultList, error) {
result := BuildResultList{}
err := xml.Unmarshal(data, &result)
if err != nil {
return nil, err
}
return &result, nil
}
func (c *ObsClient) BuildStatus(project string) (*BuildResultList, error) {
u := c.baseUrl.JoinPath("build", project, "_result")
query := u.Query()
query.Add("view", "status")
query.Add("view", "binarylist")
query.Add("multibuild", "1")
u.RawQuery = query.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
log.Print(u.String())
if err != nil {
return nil, err
}
req.SetBasicAuth(c.user, c.password)
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
if res.StatusCode != 200 {
return nil, fmt.Errorf("Unexpected return code: %d", res.StatusCode)
}
data, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
return parseBuildResults(data)
}