forked from misaka00251/go2spec
131 lines
3.2 KiB
Go
131 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"golang.org/x/net/html"
|
|
)
|
|
|
|
// To update, use:
|
|
// curl -s https://api.github.com/licenses | jq '.[].key'
|
|
var githubLicenseToSPDXLicense = map[string]string{
|
|
//"agpl-3.0"
|
|
"apache-2.0": "Apache-2.0",
|
|
"artistic-2.0": "Artistic-2.0",
|
|
"bsd-2-clause": "BSD-2-Clause",
|
|
"bsd-3-clause": "BSD-3-Clause",
|
|
"cc0-1.0": "CC0-1.0",
|
|
//"epl-1.0" (eclipse public license)
|
|
"gpl-2.0": "GPL-2.0-only",
|
|
"gpl-3.0": "GPL-3.0-only",
|
|
"isc": "ISC",
|
|
"lgpl-2.1": "LGPL-2.1-only",
|
|
"lgpl-3.0": "LGPL-3.0-only",
|
|
"mit": "MIT",
|
|
"mpl-2.0": "MPL-2.0",
|
|
//"unlicense"
|
|
}
|
|
|
|
var githubRegexp = regexp.MustCompile(`github\.com/([^/]+/[^/]+)`)
|
|
|
|
func findGitHubOwnerRepo(gopkg string) (string, error) {
|
|
if strings.HasPrefix(gopkg, "github.com/") {
|
|
return strings.TrimPrefix(gopkg, "github.com/"), nil
|
|
}
|
|
resp, err := http.Get("https://" + gopkg + "?go-get=1")
|
|
if err != nil {
|
|
return "", fmt.Errorf("HTTP get: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
z := html.NewTokenizer(resp.Body)
|
|
for {
|
|
tt := z.Next()
|
|
if tt == html.ErrorToken {
|
|
return "", fmt.Errorf("%q is not on GitHub", gopkg)
|
|
}
|
|
token := z.Token()
|
|
if token.Data != "meta" {
|
|
continue
|
|
}
|
|
var meta struct {
|
|
name, content string
|
|
}
|
|
for _, attr := range token.Attr {
|
|
if attr.Key == "name" {
|
|
meta.name = attr.Val
|
|
}
|
|
if attr.Key == "content" {
|
|
meta.content = attr.Val
|
|
}
|
|
}
|
|
|
|
match := func(name string, length int) string {
|
|
if f := strings.Fields(meta.content); meta.name == name && len(f) == length {
|
|
if f[0] != gopkg {
|
|
return ""
|
|
}
|
|
if repoMatch := githubRegexp.FindStringSubmatch(f[2]); repoMatch != nil {
|
|
return strings.TrimSuffix(repoMatch[1], ".git")
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
if repo := match("go-import", 3); repo != "" {
|
|
return repo, nil
|
|
}
|
|
if repo := match("go-source", 4); repo != "" {
|
|
return repo, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
func findGitHubRepo(gopkg string) (owner string, repo string, _ error) {
|
|
ownerrepo, err := findGitHubOwnerRepo(gopkg)
|
|
if err != nil {
|
|
return "", "", fmt.Errorf("find GitHub owner repo: %w", err)
|
|
}
|
|
parts := strings.Split(ownerrepo, "/")
|
|
if got, want := len(parts), 2; got != want {
|
|
return "", "", fmt.Errorf("invalid GitHub repo: %q does not follow owner/repo", repo)
|
|
}
|
|
return parts[0], parts[1], nil
|
|
}
|
|
|
|
func getLicenseForGopkg(gopkg string) (string, error) {
|
|
owner, repo, err := findGitHubRepo(gopkg)
|
|
if err != nil {
|
|
return "", fmt.Errorf("find GitHub repo: %w", err)
|
|
}
|
|
|
|
rl, _, err := gitHub.Repositories.License(context.TODO(), owner, repo)
|
|
if err != nil {
|
|
return "", fmt.Errorf("get license for Go package: %w", err)
|
|
}
|
|
|
|
if license, ok := githubLicenseToSPDXLicense[rl.GetLicense().GetKey()]; ok {
|
|
return license, nil
|
|
}
|
|
|
|
return "TODO", nil
|
|
}
|
|
|
|
// getDescriptionForGopkg gets the package description from GitHub,
|
|
// intended for the synopsis or the short description in debian/control.
|
|
func getDescriptionForGopkg(gopkg string) (string, error) {
|
|
owner, repo, err := findGitHubRepo(gopkg)
|
|
if err != nil {
|
|
return "", fmt.Errorf("find GitHub repo: %w", err)
|
|
}
|
|
|
|
rr, _, err := gitHub.Repositories.Get(context.TODO(), owner, repo)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return strings.TrimSpace(rr.GetDescription()), nil
|
|
}
|