summaryrefslogtreecommitdiff
path: root/repo_host.go
diff options
context:
space:
mode:
Diffstat (limited to 'repo_host.go')
-rw-r--r--repo_host.go92
1 files changed, 92 insertions, 0 deletions
diff --git a/repo_host.go b/repo_host.go
new file mode 100644
index 0000000..2fdd4cc
--- /dev/null
+++ b/repo_host.go
@@ -0,0 +1,92 @@
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+)
+
+// A RepoHost hosts repositories, and can be queried as to whether it hosts a
+// repository with a specific name.
+type RepoHost interface {
+ HostsRepo(ctx context.Context, name string) (string, bool, error)
+}
+
+// Sourcehut is a RepoHost
+//
+// https://git.sr.ht
+type Sourcehut struct {
+ Token string // a personal access token
+ Username string // the username
+}
+
+// HostsRepo implements RepoHost
+func (s Sourcehut) HostsRepo(ctx context.Context, name string) (string, bool, error) {
+ endpoint := "https://git.sr.ht/api/~" + s.Username + "/repos/" + name
+ type response struct {
+ Name string `json:"name"`
+ Visibility string `json:"visibility"`
+ }
+ var repo response
+ if err := makeRequest(ctx, &repo, endpoint, "token "+s.Token); err != nil {
+ return "", false, err
+ }
+ if repo.Visibility != "public" || repo.Name == "" {
+ return "", false, nil
+ }
+ return "https://git.sr.ht/~" + s.Username + "/" + repo.Name, true, nil
+}
+
+// Github is a RepoHost
+//
+// https://github.com
+type Github struct {
+ Username string
+ Token string
+}
+
+// HostsRepo implements RepoHost
+func (g Github) HostsRepo(ctx context.Context, name string) (string, bool, error) {
+ endpoint := "https://api.github.com/repos/" + g.Username + "/" + name
+ type response struct {
+ URL string `json:"html_url"`
+ Private bool `json:"private"`
+ }
+ var repo response
+ if err := makeRequest(ctx, &repo, endpoint, "token "+g.Token); err != nil {
+ return "", false, err
+ }
+ if repo.Private || repo.URL == "" {
+ return "", false, nil
+ }
+ return repo.URL, true, nil
+}
+
+func makeRequest(ctx context.Context, out interface{}, url string, auth string) error {
+ req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
+ if err != nil {
+ return err
+ }
+ req.Header.Set("Authorization", auth)
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return err
+ }
+ if resp.StatusCode == http.StatusNotFound {
+ return nil
+ }
+ if resp.StatusCode != http.StatusOK {
+ return fmt.Errorf("get %s: %s", url, resp.Status)
+ }
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return err
+ }
+ if err := json.Unmarshal(body, out); err != nil {
+ return err
+ }
+ return nil
+}