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
}
|