pip compatible server to serve Python packages out of GitHub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

171 lines
3.5 KiB

package pypihub
import (
"fmt"
"io"
"net/http"
"net/url"
"strings"
"github.com/google/go-github/github"
)
type Client struct {
config Config
client *github.Client
repos []string
}
func NewClient(cfg Config) *Client {
var t = github.BasicAuthTransport{
Username: cfg.Username,
Password: cfg.AccessToken,
}
return &Client{
config: cfg,
client: github.NewClient(t.Client()),
repos: cfg.RepoNames,
}
}
func (c *Client) splitRepoName(r string) (string, string) {
var p = strings.SplitN(r, "/", 2)
switch len(p) {
case 2:
return p[0], p[1]
case 1:
return c.config.Username, p[0]
default:
return "", ""
}
}
func (c *Client) getRepoTagAssets(owner string, repo string) ([]Asset, error) {
var tags []*github.RepositoryTag
var err error
tags, _, err = c.client.Repositories.ListTags(owner, repo, nil)
if err != nil {
return nil, err
}
var allAssets = make([]Asset, 0)
for _, tag := range tags {
// Remove any `v` prefix, e.g. `v1.0.0` -> `1.0.0`
var name = strings.Trim(*tag.Name, "v")
name = fmt.Sprintf("%s-%s.tar.gz", repo, name)
allAssets = append(allAssets, Asset{
Name: name,
Owner: owner,
Repo: repo,
Ref: *tag.Name,
Format: "tarball",
})
}
return allAssets, nil
}
func (c *Client) GetRepoAssets(r string) ([]Asset, error) {
var owner, repo string
owner, repo = c.splitRepoName(r)
var releases []*github.RepositoryRelease
var err error
releases, _, err = c.client.Repositories.ListReleases(owner, repo, nil)
if err != nil {
return nil, err
}
if len(releases) == 0 {
return c.getRepoTagAssets(owner, repo)
}
var allAssets = make([]Asset, 0)
for _, rel := range releases {
var assets []*github.ReleaseAsset
assets, _, err = c.client.Repositories.ListReleaseAssets(owner, repo, *rel.ID, nil)
if err != nil {
return nil, err
}
var hasTar = false
for _, a := range assets {
if strings.HasSuffix(*a.Name, ".tar.gz") {
hasTar = true
}
allAssets = append(allAssets, Asset{
ID: *a.ID,
Name: *a.Name,
Owner: owner,
Repo: repo,
})
}
if hasTar == false {
// Remove any `v` prefix, e.g. `v1.0.0` -> `1.0.0`
var name = strings.Trim(*rel.Name, "v")
name = fmt.Sprintf("%s-%s.tar.gz", repo, name)
allAssets = append(allAssets, Asset{
Name: name,
Owner: owner,
Repo: repo,
Ref: *rel.TagName,
Format: "tarball",
})
}
}
return allAssets, nil
}
func (c *Client) GetAllAssets() ([]Asset, error) {
var allAssets = make([]Asset, 0)
for _, r := range c.config.RepoNames {
var repoAssets = make([]Asset, 0)
var err error
repoAssets, err = c.GetRepoAssets(r)
if err != nil {
return nil, err
}
allAssets = append(allAssets, repoAssets...)
}
return allAssets, nil
}
func (c *Client) DownloadAsset(a Asset) (io.ReadCloser, error) {
var rc io.ReadCloser
var redirect string
var err error
rc, redirect, err = c.client.Repositories.DownloadReleaseAsset(a.Owner, a.Repo, a.ID)
if rc == nil {
var resp *http.Response
resp, err = http.Get(redirect)
if err != nil {
return nil, err
}
rc = resp.Body
}
return rc, err
}
func (c *Client) DownloadArchive(a Asset) (io.ReadCloser, error) {
var f = github.Tarball
if a.Format == "zipball" {
f = github.Zipball
}
var u *url.URL
var err error
u, _, err = c.client.Repositories.GetArchiveLink(a.Owner, a.Repo, f, nil)
if err != nil {
return nil, err
}
var resp *http.Response
resp, err = http.Get(u.String())
if err != nil {
return nil, err
}
return resp.Body, nil
}