diff options
| author | Paul Buetow <paul@buetow.org> | 2025-06-27 23:24:36 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-06-27 23:24:36 +0300 |
| commit | 79e882713b195e4674dc693169ecf7dbf956a91e (patch) | |
| tree | b00325ea3f519676bc389cce735447249bef69a6 /internal/codeberg/codeberg.go | |
| parent | 59d7b258cff47b0640f44f1068460403459a4bde (diff) | |
feat: implement --create-codeberg-repos
Diffstat (limited to 'internal/codeberg/codeberg.go')
| -rw-r--r-- | internal/codeberg/codeberg.go | 105 |
1 files changed, 103 insertions, 2 deletions
diff --git a/internal/codeberg/codeberg.go b/internal/codeberg/codeberg.go index 4f0a76d..1cf5659 100644 --- a/internal/codeberg/codeberg.go +++ b/internal/codeberg/codeberg.go @@ -1,9 +1,12 @@ package codeberg import ( + "bytes" "encoding/json" "fmt" "net/http" + "os" + "path/filepath" "time" ) @@ -28,14 +31,45 @@ type Repository struct { type Client struct { baseURL string org string + token string } // NewClient creates a new Codeberg API client -func NewClient(org string) Client { - return Client{ +func NewClient(org, token string) Client { + c := Client{ baseURL: "https://codeberg.org/api/v1", org: org, } + c.loadToken(token) + return c +} + +// loadToken loads the Codeberg API token from config, env, or file +func (c *Client) loadToken(tokenFromConfig string) { + if tokenFromConfig != "" { + c.token = tokenFromConfig + return + } + + // Check environment variable + if token := os.Getenv("CODEBERG_TOKEN"); token != "" { + c.token = token + return + } + + // Check token file + home, err := os.UserHomeDir() + if err == nil { + tokenFile := filepath.Join(home, ".gitsyncer_codeberg_token") + if data, err := os.ReadFile(tokenFile); err == nil { + c.token = string(data) + } + } +} + +// HasToken returns true if a token is loaded +func (c *Client) HasToken() bool { + return c.token != "" } // ListPublicRepos lists all public repositories for an organization @@ -130,3 +164,70 @@ func GetRepoNames(repos []Repository) []string { } return names } + +// RepoExists checks if a repository exists on Codeberg +func (c *Client) RepoExists(repoName string) (bool, error) { + url := fmt.Sprintf("%s/repos/%s/%s", c.baseURL, c.org, repoName) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return false, err + } + + if c.HasToken() { + req.Header.Set("Authorization", "token "+c.token) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return false, err + } + defer resp.Body.Close() + + return resp.StatusCode == 200, nil +} + +// CreateRepo creates a new repository on Codeberg +func (c *Client) CreateRepo(repoName, description string, private bool) error { + exists, err := c.RepoExists(repoName) + if err != nil { + return fmt.Errorf("failed to check if repo exists: %w", err) + } + if exists { + return nil // Repository already exists + } + + url := fmt.Sprintf("%s/user/repos", c.baseURL) + + payload := map[string]interface{}{ + "name": repoName, + "description": description, + "private": private, + } + + body, err := json.Marshal(payload) + if err != nil { + return err + } + + req, err := http.NewRequest("POST", url, bytes.NewBuffer(body)) + if err != nil { + return err + } + + req.Header.Set("Content-Type", "application/json") + if c.HasToken() { + req.Header.Set("Authorization", "token "+c.token) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusCreated { + return fmt.Errorf("failed to create repository: status code %d", resp.StatusCode) + } + + return nil +} |
