mirror of
https://github.com/gomods/athens
synced 2026-02-03 11:00:32 +00:00
Athens: move storage.NotFound to errors.NotFound (#373)
* Athens: move storage.NotFound to errors.NotFound * see where things went wrong * empty means unexpected * GCP: replace AlreadyExists err * resolve conflicts * Errors: change not found name * fix build
This commit is contained in:
@@ -49,7 +49,7 @@ func (p *protocol) List(ctx context.Context, mod string) ([]string, error) {
|
||||
func (p *protocol) Info(ctx context.Context, mod, ver string) ([]byte, error) {
|
||||
const op errors.Op = "protocol.Info"
|
||||
v, err := p.s.Get(ctx, mod, ver)
|
||||
if storage.IsNotFoundError(err) {
|
||||
if errors.IsNotFoundErr(err) {
|
||||
v, err = p.fillCache(ctx, mod, ver)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -87,7 +87,7 @@ func (p *protocol) Latest(ctx context.Context, mod string) (*storage.RevInfo, er
|
||||
func (p *protocol) GoMod(ctx context.Context, mod, ver string) ([]byte, error) {
|
||||
const op errors.Op = "protocol.GoMod"
|
||||
v, err := p.s.Get(ctx, mod, ver)
|
||||
if storage.IsNotFoundError(err) {
|
||||
if errors.IsNotFoundErr(err) {
|
||||
v, err = p.fillCache(ctx, mod, ver)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -100,7 +100,7 @@ func (p *protocol) GoMod(ctx context.Context, mod, ver string) ([]byte, error) {
|
||||
func (p *protocol) Zip(ctx context.Context, mod, ver string) (io.ReadCloser, error) {
|
||||
const op errors.Op = "protocol.Zip"
|
||||
v, err := p.s.Get(ctx, mod, ver)
|
||||
if storage.IsNotFoundError(err) {
|
||||
if errors.IsNotFoundErr(err) {
|
||||
v, err = p.fillCache(ctx, mod, ver)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -113,7 +113,7 @@ func (p *protocol) Zip(ctx context.Context, mod, ver string) (io.ReadCloser, err
|
||||
func (p *protocol) Version(ctx context.Context, mod, ver string) (*storage.Version, error) {
|
||||
const op errors.Op = "protocol.Version"
|
||||
v, err := p.s.Get(ctx, mod, ver)
|
||||
if errors.ErrNotFound(err) {
|
||||
if errors.IsNotFoundErr(err) {
|
||||
v, err = p.fillCache(ctx, mod, ver)
|
||||
}
|
||||
if err != nil {
|
||||
|
||||
@@ -91,7 +91,7 @@ func E(op Op, args ...interface{}) error {
|
||||
}
|
||||
}
|
||||
if e.Err == nil {
|
||||
e.Err = errors.New("no error message provided")
|
||||
e.Err = errors.New(KindText(e))
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package errors
|
||||
|
||||
// ErrNotFound helper function for KindNotFound
|
||||
func ErrNotFound(err error) bool {
|
||||
// IsNotFoundErr helper function for KindNotFound
|
||||
func IsNotFoundErr(err error) bool {
|
||||
return Kind(err) == KindNotFound
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import "context"
|
||||
|
||||
// Deleter deletes module metadata and its source from underlying storage
|
||||
type Deleter interface {
|
||||
// Delete must return ErrVersionNotFound if the module/version are not
|
||||
// Delete must return ErrNotFound if the module/version are not
|
||||
// found.
|
||||
Delete(ctx context.Context, module, vsn string) error
|
||||
}
|
||||
|
||||
@@ -3,20 +3,18 @@ package fs
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
)
|
||||
|
||||
// Delete removes a specific version of a module.
|
||||
func (v *storageImpl) Delete(ctx context.Context, module, version string) error {
|
||||
const op errors.Op = "fs.Delete"
|
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "storage.fs.Delete")
|
||||
defer sp.Finish()
|
||||
versionedPath := v.versionLocation(module, version)
|
||||
if !v.Exists(ctx, module, version) {
|
||||
return storage.ErrVersionNotFound{
|
||||
Module: module,
|
||||
Version: version,
|
||||
}
|
||||
return errors.E(op, errors.M(module), errors.V(version), errors.KindNotFound)
|
||||
}
|
||||
return v.filesystem.RemoveAll(versionedPath)
|
||||
}
|
||||
|
||||
@@ -5,29 +5,30 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
||||
func (v *storageImpl) Get(ctx context.Context, module, version string) (*storage.Version, error) {
|
||||
const op errors.Op = "fs.Get"
|
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "storage.fs.Get")
|
||||
defer sp.Finish()
|
||||
versionedPath := v.versionLocation(module, version)
|
||||
mod, err := afero.ReadFile(v.filesystem, filepath.Join(versionedPath, "go.mod"))
|
||||
if err != nil {
|
||||
return nil, storage.ErrVersionNotFound{Module: module, Version: version}
|
||||
return nil, errors.E(op, errors.M(module), errors.V(version), errors.KindNotFound)
|
||||
}
|
||||
|
||||
src, err := v.filesystem.OpenFile(filepath.Join(versionedPath, "source.zip"), os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
return nil, storage.ErrVersionNotFound{Module: module, Version: version}
|
||||
return nil, errors.E(op, errors.M(module), errors.V(version), errors.KindNotFound)
|
||||
}
|
||||
|
||||
info, err := afero.ReadFile(v.filesystem, filepath.Join(versionedPath, version+".info"))
|
||||
if err != nil {
|
||||
return nil, storage.ErrVersionNotFound{Module: module, Version: version}
|
||||
return nil, errors.E(op, errors.M(module), errors.V(version), errors.KindNotFound)
|
||||
}
|
||||
|
||||
// TODO: store the time in the saver, and parse it here
|
||||
|
||||
@@ -2,10 +2,10 @@ package gcp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"cloud.google.com/go/storage"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
"google.golang.org/api/iterator"
|
||||
)
|
||||
|
||||
@@ -15,11 +15,22 @@ type gcpBucket struct {
|
||||
}
|
||||
|
||||
func (b *gcpBucket) Delete(ctx context.Context, path string) error {
|
||||
return b.Object(path).Delete(ctx)
|
||||
const op errors.Op = "gcpBucket.Delete"
|
||||
err := b.Object(path).Delete(ctx)
|
||||
if err != nil {
|
||||
return errors.E(op, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *gcpBucket) Open(ctx context.Context, path string) (io.ReadCloser, error) {
|
||||
return b.Object(path).NewReader(ctx)
|
||||
const op errors.Op = "gcpBucket.Open"
|
||||
rc, err := b.Object(path).NewReader(ctx)
|
||||
if err != nil {
|
||||
return rc, errors.E(op, err, errors.M(path))
|
||||
}
|
||||
return rc, nil
|
||||
}
|
||||
|
||||
func (b *gcpBucket) Write(ctx context.Context, path string) io.WriteCloser {
|
||||
@@ -27,6 +38,7 @@ func (b *gcpBucket) Write(ctx context.Context, path string) io.WriteCloser {
|
||||
}
|
||||
|
||||
func (b *gcpBucket) List(ctx context.Context, prefix string) ([]string, error) {
|
||||
const op errors.Op = "gcpBucket.List"
|
||||
it := b.Objects(ctx, &storage.Query{Prefix: prefix})
|
||||
|
||||
res := []string{}
|
||||
@@ -36,7 +48,7 @@ func (b *gcpBucket) List(ctx context.Context, prefix string) ([]string, error) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not iterate over query: %s", err)
|
||||
return nil, errors.E(op, err)
|
||||
}
|
||||
res = append(res, attrs.Name)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/gomods/athens/pkg/config"
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
modupl "github.com/gomods/athens/pkg/storage/module"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
)
|
||||
@@ -13,10 +13,11 @@ import (
|
||||
// removes a version of a module from storage. Returning ErrNotFound
|
||||
// if the version does not exist.
|
||||
func (s *Storage) Delete(ctx context.Context, module, version string) error {
|
||||
const op errors.Op = "gcp.Delete"
|
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "storage.gcp.Delete")
|
||||
defer sp.Finish()
|
||||
if exists := s.bucket.Exists(ctx, config.PackageVersionedName(module, version, "mod")); !exists {
|
||||
return storage.ErrVersionNotFound{Module: module, Version: version}
|
||||
return errors.E(op, errors.M(module), errors.V(version), errors.KindNotFound)
|
||||
}
|
||||
|
||||
return modupl.Delete(ctx, module, version, s.bucket.Delete)
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
athensStorage "github.com/gomods/athens/pkg/storage"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
)
|
||||
|
||||
func (g *GcpTests) TestSaveGetListExistsRoundTrip() {
|
||||
@@ -67,8 +67,7 @@ func (g *GcpTests) TestNotFounds() {
|
||||
|
||||
g.T().Run("Get module version not found", func(t *testing.T) {
|
||||
_, err := g.store.Get(context.Background(), "never", "there")
|
||||
versionNotFoundErr := athensStorage.ErrVersionNotFound{Module: "never", Version: "there"}
|
||||
r.EqualError(versionNotFoundErr, err.Error())
|
||||
r.True(errors.IsNotFoundErr(err))
|
||||
})
|
||||
|
||||
g.T().Run("Exists module version not found", func(t *testing.T) {
|
||||
@@ -77,7 +76,6 @@ func (g *GcpTests) TestNotFounds() {
|
||||
|
||||
g.T().Run("List not found", func(t *testing.T) {
|
||||
_, err := g.store.List(g.context, "nothing/to/see/here")
|
||||
modNotFoundErr := athensStorage.ErrNotFound{Module: "nothing/to/see/here"}
|
||||
r.EqualError(modNotFoundErr, err.Error())
|
||||
r.True(errors.IsNotFoundErr(err))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/gomods/athens/pkg/config"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
)
|
||||
@@ -14,37 +15,38 @@ import (
|
||||
//
|
||||
// The caller is responsible for calling close on the Zip ReadCloser
|
||||
func (s *Storage) Get(ctx context.Context, module, version string) (*storage.Version, error) {
|
||||
const op errors.Op = "gcp.Get"
|
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "storage.gcp.Get")
|
||||
defer sp.Finish()
|
||||
if exists := s.Exists(ctx, module, version); !exists {
|
||||
return nil, storage.ErrVersionNotFound{Module: module, Version: version}
|
||||
if !s.Exists(ctx, module, version) {
|
||||
return nil, errors.E(op, errors.M(module), errors.V(version), errors.KindNotFound)
|
||||
}
|
||||
|
||||
modReader, err := s.bucket.Open(ctx, config.PackageVersionedName(module, version, "mod"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get new reader for mod file: %s", err)
|
||||
return nil, errors.E(op, err)
|
||||
}
|
||||
modBytes, err := ioutil.ReadAll(modReader)
|
||||
modReader.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read bytes of mod file: %s", err)
|
||||
return nil, errors.E(op, fmt.Errorf("could not get new reader for mod file: %s", err))
|
||||
}
|
||||
|
||||
zipReader, err := s.bucket.Open(ctx, config.PackageVersionedName(module, version, "zip"))
|
||||
// It is up to the caller to call Close on this reader.
|
||||
// The storage.Version contains a ReadCloser for the zip.
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get new reader for zip file: %s", err)
|
||||
return nil, errors.E(op, err)
|
||||
}
|
||||
|
||||
infoReader, err := s.bucket.Open(ctx, config.PackageVersionedName(module, version, "info"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get new reader for info file: %s", err)
|
||||
return nil, errors.E(op, err)
|
||||
}
|
||||
infoBytes, err := ioutil.ReadAll(infoReader)
|
||||
infoReader.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read bytes of info file: %s", err)
|
||||
return nil, errors.E(op, fmt.Errorf("could not read bytes of info file: %s", err))
|
||||
}
|
||||
return &storage.Version{Mod: modBytes, Zip: zipReader, Info: infoBytes}, nil
|
||||
}
|
||||
|
||||
@@ -4,13 +4,14 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
)
|
||||
|
||||
// List implements the (./pkg/storage).Lister interface
|
||||
// It returns a list of versions, if any, for a given module
|
||||
func (s *Storage) List(ctx context.Context, module string) ([]string, error) {
|
||||
const op errors.Op = "gcp.List"
|
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "storage.gcp.List")
|
||||
defer sp.Finish()
|
||||
paths, err := s.bucket.List(ctx, module)
|
||||
@@ -19,7 +20,7 @@ func (s *Storage) List(ctx context.Context, module string) ([]string, error) {
|
||||
}
|
||||
versions := extractVersions(paths)
|
||||
if len(versions) < 1 {
|
||||
return nil, storage.ErrNotFound{Module: module}
|
||||
return nil, errors.E(op, "empty versions list", errors.M(module), errors.KindNotFound)
|
||||
}
|
||||
return versions, nil
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
|
||||
stg "github.com/gomods/athens/pkg/storage"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
|
||||
moduploader "github.com/gomods/athens/pkg/storage/module"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
)
|
||||
@@ -19,10 +20,11 @@ import (
|
||||
// Uploaded files are publicly accessable in the storage bucket as per
|
||||
// an ACL rule.
|
||||
func (s *Storage) Save(ctx context.Context, module, version string, mod []byte, zip io.Reader, info []byte) error {
|
||||
const op errors.Op = "gcp.Save"
|
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "storage.gcp.Save")
|
||||
defer sp.Finish()
|
||||
if exists := s.Exists(ctx, module, version); exists {
|
||||
return stg.ErrVersionAlreadyExists{Module: module, Version: version}
|
||||
return errors.E(op, "already exists", errors.M(module), errors.V(version), errors.KindAlreadyExists)
|
||||
}
|
||||
|
||||
err := moduploader.Upload(ctx, module, version, bytes.NewReader(info), bytes.NewReader(mod), zip, s.upload)
|
||||
|
||||
@@ -4,31 +4,33 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
)
|
||||
|
||||
func (v *storageImpl) Delete(ctx context.Context, module, version string) error {
|
||||
const op errors.Op = "minio.Delete"
|
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "storage.minio.Delete")
|
||||
defer sp.Finish()
|
||||
if !v.Exists(ctx, module, version) {
|
||||
return storage.ErrVersionNotFound{
|
||||
Module: module,
|
||||
Version: version,
|
||||
}
|
||||
return errors.E(op, errors.M(module), errors.V(version), errors.KindNotFound)
|
||||
}
|
||||
versionedPath := v.versionLocation(module, version)
|
||||
|
||||
modPath := fmt.Sprintf("%s/go.mod", versionedPath)
|
||||
if err := v.minioClient.RemoveObject(v.bucketName, modPath); err != nil {
|
||||
return err
|
||||
return errors.E(op, err)
|
||||
}
|
||||
|
||||
zipPath := fmt.Sprintf("%s/source.zip", versionedPath)
|
||||
if err := v.minioClient.RemoveObject(v.bucketName, zipPath); err != nil {
|
||||
return err
|
||||
return errors.E(op, err)
|
||||
}
|
||||
|
||||
infoPath := fmt.Sprintf("%s/%s.info", versionedPath, version)
|
||||
return v.minioClient.RemoveObject(v.bucketName, infoPath)
|
||||
err := v.minioClient.RemoveObject(v.bucketName, infoPath)
|
||||
if err != nil {
|
||||
return errors.E(op, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
minio "github.com/minio/minio-go"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
@@ -48,9 +49,10 @@ func (v *storageImpl) Get(ctx context.Context, module, version string) (*storage
|
||||
}
|
||||
|
||||
func transformNotFoundErr(module, version string, err error) error {
|
||||
const op errors.Op = "minio.transformNotFoundErr"
|
||||
if eresp, ok := err.(minio.ErrorResponse); ok {
|
||||
if eresp.StatusCode == http.StatusNotFound {
|
||||
return storage.ErrVersionNotFound{Module: module, Version: version}
|
||||
return errors.E(op, errors.M(module), errors.V(version), errors.KindNotFound)
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/globalsign/mgo/bson"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
)
|
||||
|
||||
@@ -15,10 +14,7 @@ func (s *ModuleStore) Delete(ctx context.Context, module, version string) error
|
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "storage.mongo.Delete")
|
||||
defer sp.Finish()
|
||||
if !s.Exists(ctx, module, version) {
|
||||
return storage.ErrVersionNotFound{
|
||||
Module: module,
|
||||
Version: version,
|
||||
}
|
||||
return errors.E(op, errors.M(module), errors.V(version), errors.KindNotFound)
|
||||
}
|
||||
db := s.s.DB(s.d)
|
||||
c := db.C(s.c)
|
||||
|
||||
@@ -20,7 +20,7 @@ func (s *ModuleStore) Get(ctx context.Context, module, vsn string) (*storage.Ver
|
||||
err := c.Find(bson.M{"module": module, "version": vsn}).One(result)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
err = storage.ErrVersionNotFound{Module: module, Version: vsn}
|
||||
err = errors.E(op, errors.M(module), errors.V(vsn), errors.KindNotFound)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/globalsign/mgo/bson"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
)
|
||||
|
||||
// List lists all versions of a module
|
||||
func (s *ModuleStore) List(ctx context.Context, module string) ([]string, error) {
|
||||
const op errors.Op = "mongo.List"
|
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "storage.mongo.List")
|
||||
defer sp.Finish()
|
||||
c := s.s.DB(s.d).C(s.c)
|
||||
@@ -18,7 +20,7 @@ func (s *ModuleStore) List(ctx context.Context, module string) ([]string, error)
|
||||
err := c.Find(bson.M{"module": module}).All(&result)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
err = storage.ErrNotFound{Module: module}
|
||||
err = errors.E(op, err, errors.M(module), errors.KindNotFound)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ErrNotFound is an error implementation that indicates a module
|
||||
// doesn't exist
|
||||
type ErrNotFound struct {
|
||||
Module string
|
||||
}
|
||||
|
||||
func (n ErrNotFound) Error() string {
|
||||
return fmt.Sprintf("module %s not found", n.Module)
|
||||
}
|
||||
|
||||
// ErrVersionNotFound is an error implementation that indicates a module
|
||||
// at a specific version doesn't exist
|
||||
type ErrVersionNotFound struct {
|
||||
Module string
|
||||
Version string
|
||||
}
|
||||
|
||||
func (e ErrVersionNotFound) Error() string {
|
||||
return fmt.Sprintf("module %s@%s not found", e.Module, e.Version)
|
||||
}
|
||||
|
||||
// IsNotFoundError returns true if err is an ErrNotFound
|
||||
func IsNotFoundError(err error) bool {
|
||||
if _, ok := err.(ErrNotFound); ok {
|
||||
return ok
|
||||
}
|
||||
|
||||
_, ok := err.(ErrVersionNotFound)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrVersionAlreadyExists is an error implementation that indicates that a
|
||||
// module@version already exists
|
||||
type ErrVersionAlreadyExists struct {
|
||||
Module string
|
||||
Version string
|
||||
}
|
||||
|
||||
func (e ErrVersionAlreadyExists) Error() string {
|
||||
return fmt.Sprintf("%s@%s already exists", e.Module, e.Version)
|
||||
}
|
||||
|
||||
// IsVersionAlreadyExistsErr returns true if err is an ErrVersionAlreadyExists
|
||||
func IsVersionAlreadyExistsErr(err error) bool {
|
||||
_, ok := err.(ErrVersionAlreadyExists)
|
||||
return ok
|
||||
}
|
||||
@@ -3,25 +3,23 @@ package rdbms
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
"github.com/gomods/athens/pkg/storage/rdbms/models"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
)
|
||||
|
||||
// Delete removes a specific version of a module.
|
||||
func (r *ModuleStore) Delete(ctx context.Context, module, version string) error {
|
||||
const op errors.Op = "rdbms.Delete"
|
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "storage.rdbms.Delete")
|
||||
defer sp.Finish()
|
||||
if !r.Exists(ctx, module, version) {
|
||||
return storage.ErrVersionNotFound{
|
||||
Module: module,
|
||||
Version: version,
|
||||
}
|
||||
return errors.E(op, errors.M(module), errors.V(version), errors.KindNotFound)
|
||||
}
|
||||
result := &models.Module{}
|
||||
query := r.conn.Where("module = ?", module).Where("version = ?", version)
|
||||
if err := query.First(result); err != nil {
|
||||
return err
|
||||
return errors.E(op, err)
|
||||
}
|
||||
return r.conn.Destroy(result)
|
||||
}
|
||||
|
||||
@@ -6,23 +6,25 @@ import (
|
||||
"database/sql"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
"github.com/gomods/athens/pkg/storage/rdbms/models"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
"github.com/pkg/errors"
|
||||
pkgerrors "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Get a specific version of a module
|
||||
func (r *ModuleStore) Get(ctx context.Context, module, vsn string) (*storage.Version, error) {
|
||||
const op errors.Op = "rdbms.Get"
|
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "storage.rdbms.Get")
|
||||
defer sp.Finish()
|
||||
result := models.Module{}
|
||||
query := r.conn.Where("module = ?", module).Where("version = ?", vsn)
|
||||
if err := query.First(&result); err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, storage.ErrVersionNotFound{Module: module, Version: vsn}
|
||||
if pkgerrors.Cause(err) == sql.ErrNoRows { // can we just say err == sql.ErrNoRows?
|
||||
return nil, errors.E(op, errors.M(module), errors.V(vsn), errors.KindNotFound)
|
||||
}
|
||||
return nil, err
|
||||
return nil, errors.E(op, err)
|
||||
}
|
||||
return &storage.Version{
|
||||
Mod: result.Mod,
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gobuffalo/suite"
|
||||
"github.com/gomods/athens/pkg/errors"
|
||||
"github.com/gomods/athens/pkg/storage"
|
||||
"github.com/gomods/athens/pkg/storage/fs"
|
||||
"github.com/gomods/athens/pkg/storage/mem"
|
||||
@@ -88,7 +89,7 @@ func (d *TestSuites) TestStorages() {
|
||||
|
||||
func (d *TestSuites) testNotFound(ts storage.TestSuite) {
|
||||
_, err := ts.Storage().Get(context.Background(), "some", "unknown")
|
||||
d.Require().Equal(true, storage.IsNotFoundError(err), "Invalid error type for %s: %#v", ts.StorageHumanReadableName(), err)
|
||||
d.Require().Equal(true, errors.IsNotFoundErr(err), "Invalid error type for %s: %#v", ts.StorageHumanReadableName(), err)
|
||||
}
|
||||
|
||||
func (d *TestSuites) testList(ts storage.TestSuite) {
|
||||
@@ -134,26 +135,24 @@ func (d *TestSuites) testDelete(ts storage.TestSuite) {
|
||||
tests := []struct {
|
||||
module string
|
||||
version string
|
||||
want error
|
||||
want int
|
||||
}{
|
||||
{
|
||||
module: "does/not/exist",
|
||||
version: "v1.0.0",
|
||||
want: storage.ErrVersionNotFound{
|
||||
Module: "does/not/exist",
|
||||
Version: "v1.0.0",
|
||||
},
|
||||
want: errors.KindNotFound,
|
||||
},
|
||||
{
|
||||
module: d.module,
|
||||
version: version,
|
||||
want: errors.KindUnexpected,
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
for _, test := range tests {
|
||||
err := ts.Storage().Delete(ctx, test.module, test.version)
|
||||
r.Equal(test.want, err)
|
||||
r.Equal(test.want, errors.Kind(err), ts.StorageHumanReadableName())
|
||||
exists := ts.Storage().Exists(ctx, test.module, test.version)
|
||||
r.Equal(false, exists)
|
||||
r.Equal(false, exists, ts.StorageHumanReadableName())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user