Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for assets in private repositories #91

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 26 additions & 26 deletions detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ type Detector interface {
// Detect takes a list of possible assets and returns a direct match. If a
// single direct match is not found, it returns a list of candidates and an
// error explaining what happened.
Detect(assets []string) (string, []string, error)
Detect(assets []Asset) (Asset, []Asset, error)
}

type DetectorChain struct {
detectors []Detector
system Detector
}

func (dc *DetectorChain) Detect(assets []string) (string, []string, error) {
func (dc *DetectorChain) Detect(assets []Asset) (Asset, []Asset, error) {
for _, d := range dc.detectors {
choice, candidates, err := d.Detect(assets)
if len(candidates) == 0 && err != nil {
return "", nil, err
return Asset{}, nil, err
} else if len(candidates) == 0 {
return choice, nil, nil
} else {
Expand All @@ -33,13 +33,13 @@ func (dc *DetectorChain) Detect(assets []string) (string, []string, error) {
}
choice, candidates, err := dc.system.Detect(assets)
if len(candidates) == 0 && err != nil {
return "", nil, err
return Asset{}, nil, err
} else if len(candidates) == 0 {
return choice, nil, nil
} else if len(candidates) >= 1 {
assets = candidates
}
return "", assets, fmt.Errorf("%d candidates found for asset chain", len(assets))
return Asset{}, assets, fmt.Errorf("%d candidates found for asset chain", len(assets))
}

// An OS represents a target operating system.
Expand Down Expand Up @@ -170,11 +170,11 @@ var goarchmap = map[string]Arch{
// candidates.
type AllDetector struct{}

func (a *AllDetector) Detect(assets []string) (string, []string, error) {
func (a *AllDetector) Detect(assets []Asset) (Asset, []Asset, error) {
if len(assets) == 1 {
return assets[0], nil, nil
}
return "", assets, fmt.Errorf("%d matches found", len(assets))
return Asset{}, assets, fmt.Errorf("%d matches found", len(assets))
}

// SingleAssetDetector finds a single named asset. If Anti is true it finds all
Expand All @@ -184,25 +184,25 @@ type SingleAssetDetector struct {
Anti bool
}

func (s *SingleAssetDetector) Detect(assets []string) (string, []string, error) {
var candidates []string
func (s *SingleAssetDetector) Detect(assets []Asset) (Asset, []Asset, error) {
var candidates []Asset
for _, a := range assets {
if !s.Anti && path.Base(a) == s.Asset {
if !s.Anti && path.Base(a.Name) == s.Asset {
return a, nil, nil
}
if !s.Anti && strings.Contains(path.Base(a), s.Asset) {
if !s.Anti && strings.Contains(path.Base(a.Name), s.Asset) {
candidates = append(candidates, a)
}
if s.Anti && !strings.Contains(path.Base(a), s.Asset) {
if s.Anti && !strings.Contains(path.Base(a.Name), s.Asset) {
candidates = append(candidates, a)
}
}
if len(candidates) == 1 {
return candidates[0], nil, nil
} else if len(candidates) > 1 {
return "", candidates, fmt.Errorf("%d candidates found for asset `%s`", len(candidates), s.Asset)
return Asset{}, candidates, fmt.Errorf("%d candidates found for asset `%s`", len(candidates), s.Asset)
}
return "", nil, fmt.Errorf("asset `%s` not found", s.Asset)
return Asset{}, nil, fmt.Errorf("asset `%s` not found", s.Asset)
}

// A SystemDetector matches a particular OS/Arch system pair.
Expand Down Expand Up @@ -234,22 +234,22 @@ func NewSystemDetector(sos, sarch string) (*SystemDetector, error) {
// match the OS are found, and no full OS/Arch matches are found, the OS
// matches are returned as candidates. Otherwise all assets are returned as
// candidates.
func (d *SystemDetector) Detect(assets []string) (string, []string, error) {
var priority []string
var matches []string
var candidates []string
all := make([]string, 0, len(assets))
func (d *SystemDetector) Detect(assets []Asset) (Asset, []Asset, error) {
var priority []Asset
var matches []Asset
var candidates []Asset
all := make([]Asset, 0, len(assets))
for _, a := range assets {
if strings.HasSuffix(a, ".sha256") || strings.HasSuffix(a, ".sha256sum") {
if strings.HasSuffix(a.Name, ".sha256") || strings.HasSuffix(a.Name, ".sha256sum") {
// skip checksums (they will be checked later by the verifier)
continue
}

os, extra := d.Os.Match(a)
os, extra := d.Os.Match(a.Name)
if extra {
priority = append(priority, a)
}
arch := d.Arch.Match(a)
arch := d.Arch.Match(a.Name)
if os && arch {
matches = append(matches, a)
}
Expand All @@ -261,17 +261,17 @@ func (d *SystemDetector) Detect(assets []string) (string, []string, error) {
if len(priority) == 1 {
return priority[0], nil, nil
} else if len(priority) > 1 {
return "", priority, fmt.Errorf("%d priority matches found", len(matches))
return Asset{}, priority, fmt.Errorf("%d priority matches found", len(matches))
} else if len(matches) == 1 {
return matches[0], nil, nil
} else if len(matches) > 1 {
return "", matches, fmt.Errorf("%d matches found", len(matches))
return Asset{}, matches, fmt.Errorf("%d matches found", len(matches))
} else if len(candidates) == 1 {
return candidates[0], nil, nil
} else if len(candidates) > 1 {
return "", candidates, fmt.Errorf("%d candidates found (unsure architecture)", len(candidates))
return Asset{}, candidates, fmt.Errorf("%d candidates found (unsure architecture)", len(candidates))
} else if len(all) == 1 {
return all[0], nil, nil
}
return "", all, fmt.Errorf("no candidates found")
return Asset{}, all, fmt.Errorf("no candidates found")
}
27 changes: 11 additions & 16 deletions dl.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ import (
"github.com/zyedidia/eget/home"
)

const (
AcceptBinary = "application/octet-stream"
AcceptGitHubJSON = "application/vnd.github+json"
)

func tokenFrom(s string) (string, error) {
if strings.HasPrefix(s, "@") {
f, err := home.Expand(s[1:])
Expand Down Expand Up @@ -50,19 +55,20 @@ func SetAuthHeader(req *http.Request) *http.Request {
fmt.Fprintln(os.Stderr, "error: cannot use GitHub token if SSL verification is disabled")
os.Exit(1)
}
req.Header.Set("Authorization", fmt.Sprintf("token %s", token))
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
}

return req
}

func Get(url string) (*http.Response, error) {
func Get(url, accept string) (*http.Response, error) {
req, err := http.NewRequest("GET", url, nil)

if err != nil {
return nil, err
}

req.Header.Set("Accept", accept)

req = SetAuthHeader(req)

proxyClient := &http.Client{Transport: &http.Transport{
Expand Down Expand Up @@ -101,21 +107,10 @@ func (r RateLimit) String() string {
}

func GetRateLimit() (RateLimit, error) {
url := "https://api.github.com/rate_limit"
req, err := http.NewRequest("GET", url, nil)
resp, err := Get("https://api.github.com/rate_limit", AcceptGitHubJSON)
if err != nil {
return RateLimit{}, err
}

req = SetAuthHeader(req)

req.Header.Set("Accept", "application/vnd.github.v3+json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
return RateLimit{}, err
}

defer resp.Body.Close()

b, err := io.ReadAll(resp.Body)
Expand Down Expand Up @@ -144,7 +139,7 @@ func Download(url string, out io.Writer, getbar func(size int64) *pb.ProgressBar
return err
}

resp, err := Get(url)
resp, err := Get(url, AcceptBinary)
if err != nil {
return err
}
Expand Down
42 changes: 23 additions & 19 deletions eget.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ func IsDirectory(path string) bool {
return fileInfo.IsDir()
}

// searches for an asset thaat has the same name as the requested one but
// searches for an asset that has the same name as the requested one but
// ending with .sha256 or .sha256sum
func checksumAsset(asset string, assets []string) string {
func checksumAsset(asset Asset, assets []Asset) Asset {
for _, a := range assets {
if a == asset+".sha256sum" || a == asset+".sha256" {
if a.Name == asset.Name+".sha256sum" || a.Name == asset.Name+".sha256" {
return a
}
}
return ""
return Asset{}
}

// Determine the appropriate Finder to use. If opts.URL is provided, we use
Expand Down Expand Up @@ -135,12 +135,12 @@ func getFinder(project string, opts *Flags) (finder Finder, tool string) {
return finder, tool
}

func getVerifier(sumAsset string, opts *Flags) (verifier Verifier, err error) {
func getVerifier(sumAsset Asset, opts *Flags) (verifier Verifier, err error) {
if opts.Verify != "" {
verifier, err = NewSha256Verifier(opts.Verify)
} else if sumAsset != "" {
} else if sumAsset != (Asset{}) {
verifier = &Sha256AssetVerifier{
AssetURL: sumAsset,
AssetURL: sumAsset.DownloadURL,
}
} else if opts.Hash {
verifier = &Sha256Printer{}
Expand Down Expand Up @@ -428,27 +428,31 @@ func main() {
fatal(err)
}

// get the url and candidates from the detector
url, candidates, err := detector.Detect(assets)
// get the asset and candidates from the detector
asset, candidates, err := detector.Detect(assets)
if len(candidates) != 0 && err != nil {
// if multiple candidates are returned, the user must select manually which one to download
fmt.Fprintf(os.Stderr, "%v: please select manually\n", err)
choices := make([]interface{}, len(candidates))
for i := range candidates {
choices[i] = path.Base(candidates[i])
choices[i] = path.Base(candidates[i].Name)
}
choice := userSelect(choices)
url = candidates[choice-1]
asset = candidates[choice-1]
} else if err != nil {
fatal(err)
}

// print the URL
fmt.Fprintf(output, "%s\n", url)
// print the download URL of the asset
if asset.Name != asset.DownloadURL {
fmt.Fprintf(output, "%s (%s)\n", asset.DownloadURL, asset.Name)
} else {
fmt.Fprintf(output, "%s\n", asset.DownloadURL)
}

// download with progress bar
buf := &bytes.Buffer{}
err = Download(url, buf, func(size int64) *pb.ProgressBar {
err = Download(asset.DownloadURL, buf, func(size int64) *pb.ProgressBar {
var pbout io.Writer = os.Stderr
if opts.Quiet {
pbout = io.Discard
Expand All @@ -474,26 +478,26 @@ func main() {
}))
})
if err != nil {
fatal(fmt.Sprintf("%s (URL: %s)", err, url))
fatal(fmt.Sprintf("%s (URL: %s)", err, asset.DownloadURL))
}

body := buf.Bytes()

sumAsset := checksumAsset(url, assets)
sumAsset := checksumAsset(asset, assets)
verifier, err := getVerifier(sumAsset, &opts)
if err != nil {
fatal(err)
}
err = verifier.Verify(body)
if err != nil {
fatal(err)
} else if opts.Verify == "" && sumAsset != "" {
fmt.Fprintf(output, "Checksum verified with %s\n", path.Base(sumAsset))
} else if opts.Verify == "" && sumAsset != (Asset{}) {
fmt.Fprintf(output, "Checksum verified with %s\n", path.Base(sumAsset.Name))
} else if opts.Verify != "" {
fmt.Fprintf(output, "Checksum verified\n")
}

extractor, err := getExtractor(url, tool, &opts)
extractor, err := getExtractor(asset.Name, tool, &opts)
if err != nil {
fatal(err)
}
Expand Down
Loading