diff --git a/go.mod b/go.mod index 504cfc92a..e06dd8472 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/aws/aws-sdk-go v1.32.7 github.com/bsm/redislock v0.4.2 github.com/codegangsta/negroni v1.0.0 // indirect + github.com/coreos/go-semver v0.2.0 github.com/fatih/color v1.7.0 github.com/go-playground/locales v0.12.1 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect @@ -50,7 +51,7 @@ require ( go.opencensus.io v0.22.3 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 // indirect golang.org/x/lint v0.0.0-20200130185559-910be7a94367 // indirect - golang.org/x/mod v0.2.0 + golang.org/x/mod v0.3.0 golang.org/x/net v0.0.0-20200222125558-5a598a2470a0 // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a diff --git a/go.sum b/go.sum index f15b7da9e..08ec3a417 100644 --- a/go.sum +++ b/go.sum @@ -420,8 +420,8 @@ golang.org/x/mod v0.1.0 h1:sfUMP1Gu8qASkorDVjnMuvgJzwFbTZSeXFiGBYAVdl4= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/pkg/download/protocol.go b/pkg/download/protocol.go index e79b7b33c..3a25cfb28 100644 --- a/pkg/download/protocol.go +++ b/pkg/download/protocol.go @@ -2,8 +2,10 @@ package download import ( "context" + "encoding/json" "io" "regexp" + "sort" "strings" "sync" @@ -13,6 +15,7 @@ import ( "github.com/gomods/athens/pkg/observ" "github.com/gomods/athens/pkg/stash" "github.com/gomods/athens/pkg/storage" + "golang.org/x/mod/semver" ) // Protocol is the download protocol which mirrors @@ -74,19 +77,27 @@ func (p *protocol) List(ctx context.Context, mod string) ([]string, error) { ctx, span := observ.StartSpan(ctx, op.String()) defer span.End() + // If the download mode is None, we won't be downloading anything from + // the internet anyway, so we should only examine local storage. + localOnly := p.df.Match(mod) == mode.None + var strList, goList []string var sErr, goErr error var wg sync.WaitGroup - wg.Add(2) + wg.Add(1) - go func() { - defer wg.Done() - strList, sErr = p.storage.List(ctx, mod) - }() + if !localOnly { + wg.Add(1) + + go func() { + defer wg.Done() + _, goList, goErr = p.lister.List(ctx, mod) + }() + } go func() { defer wg.Done() - _, goList, goErr = p.lister.List(ctx, mod) + strList, sErr = p.storage.List(ctx, mod) }() wg.Wait() @@ -145,12 +156,38 @@ func (p *protocol) Latest(ctx context.Context, mod string) (*storage.RevInfo, er const op errors.Op = "protocol.Latest" ctx, span := observ.StartSpan(ctx, op.String()) defer span.End() - lr, _, err := p.lister.List(ctx, mod) - if err != nil { - return nil, errors.E(op, err) + + localOnly := p.df.Match(mod) == mode.None + if localOnly { + sList, err := p.storage.List(ctx, mod) + if err != nil { + return nil, err + } + if len(sList) == 0 { + return nil, errors.E(op, errors.KindNotFound) + } + var sorted []string + for _, v := range sList { + sorted = append(sorted, semver.Canonical(v)) + } + sort.Slice(sorted, func(i, j int) bool { + return semver.Compare(sorted[i], sorted[j]) == -1 + }) + latest := sorted[len(sorted)-1] + bytes, err := p.storage.Info(ctx, mod, latest) + if err != nil { + return nil, err + } + var revInfo storage.RevInfo + err = json.Unmarshal(bytes, &revInfo) + if err != nil { + return nil, err + } + return &revInfo, err } - return lr, nil + revInfo, _, err := p.lister.List(ctx, mod) + return revInfo, err } func (p *protocol) Info(ctx context.Context, mod, ver string) ([]byte, error) {