summaryrefslogtreecommitdiff
path: root/repo_host.go
blob: 2fdd4cc4b6818ed025ff5bd3893b44d024d839ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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
}