feat: add blockstore: block not found matching too

This commit was moved from ipfs/go-ipfs-http-client@a3354f062c
This commit is contained in:
Jorropo 2022-04-01 00:23:55 +02:00
parent ddd36645b2
commit 775bcb7f09
3 changed files with 76 additions and 11 deletions

View File

@ -66,7 +66,7 @@ func (api *BlockAPI) Get(ctx context.Context, p path.Path) (io.Reader, error) {
return nil, err
}
if resp.Error != nil {
return nil, parseIPLDNotFoundWithFallbackToError(resp.Error)
return nil, parseErrNotFoundWithFallbackToError(resp.Error)
}
//TODO: make get return ReadCloser to avoid copying
@ -98,14 +98,14 @@ func (api *BlockAPI) Rm(ctx context.Context, p path.Path, opts ...caopts.BlockRm
return err
}
return parseIPLDNotFoundWithFallbackToMSG(removedBlock.Error)
return parseErrNotFoundWithFallbackToMSG(removedBlock.Error)
}
func (api *BlockAPI) Stat(ctx context.Context, p path.Path) (iface.BlockStat, error) {
var out blockStat
err := api.core().Request("block/stat", p.String()).Exec(ctx, &out)
if err != nil {
return nil, parseIPLDNotFoundWithFallbackToError(err)
return nil, parseErrNotFoundWithFallbackToError(err)
}
out.cid, err = cid.Parse(out.Key)
if err != nil {

View File

@ -8,6 +8,8 @@ import (
ipld "github.com/ipfs/go-ipld-format"
)
// This file handle parsing and returning the correct ABI based errors from error messages
type prePostWrappedNotFoundError struct {
pre string
post string
@ -27,8 +29,8 @@ func (e prePostWrappedNotFoundError) Unwrap() error {
return e.wrapped
}
func parseIPLDNotFoundWithFallbackToMSG(msg string) error {
err, handled := parseIPLDNotFound(msg)
func parseErrNotFoundWithFallbackToMSG(msg string) error {
err, handled := parseErrNotFound(msg)
if handled {
return err
}
@ -36,8 +38,8 @@ func parseIPLDNotFoundWithFallbackToMSG(msg string) error {
return errors.New(msg)
}
func parseIPLDNotFoundWithFallbackToError(msg error) error {
err, handled := parseIPLDNotFound(msg.Error())
func parseErrNotFoundWithFallbackToError(msg error) error {
err, handled := parseErrNotFound(msg.Error())
if handled {
return err
}
@ -57,13 +59,25 @@ func notAsciiLetterOrDigits(r rune) bool {
return notAsciiLetterOrDigitsLUT[r] > 0
}
// This file handle parsing and returning the correct ABI based errors from error messages
//lint:ignore ST1008 this function is not using the error as a mean to return failure but it massages it to return the correct type
func parseIPLDNotFound(msg string) (error, bool) {
func parseErrNotFound(msg string) (error, bool) {
if msg == "" {
return nil, true // Fast path
}
if err, handled := parseIPLDErrNotFound(msg); handled {
return err, true
}
if err, handled := parseBlockstoreNotFound(msg); handled {
return err, true
}
return nil, false
}
//lint:ignore ST1008 using error as values
func parseIPLDErrNotFound(msg string) (error, bool) {
// The patern we search for is:
const ipldErrNotFoundKey = "ipld: could not find " /*CID*/
// We try to parse the CID, if it's invalid we give up and return a simple text error.
@ -114,3 +128,33 @@ func parseIPLDNotFound(msg string) (error, bool) {
return err, true
}
// This is a simple error type that just return msg as Error().
// But that also match ipld.ErrNotFound when called with Is(err).
// That is needed to keep compatiblity with code that use string.Contains(err.Error(), "blockstore: block not found")
// and code using ipld.ErrNotFound
type blockstoreNotFoundMatchingIPLDErrNotFound struct {
msg string
}
func (e blockstoreNotFoundMatchingIPLDErrNotFound) String() string {
return e.Error()
}
func (e blockstoreNotFoundMatchingIPLDErrNotFound) Error() string {
return e.msg
}
func (e blockstoreNotFoundMatchingIPLDErrNotFound) Is(err error) bool {
_, ok := err.(ipld.ErrNotFound)
return ok
}
//lint:ignore ST1008 using error as values
func parseBlockstoreNotFound(msg string) (error, bool) {
if !strings.Contains(msg, "blockstore: block not found") {
return nil, false
}
return blockstoreNotFoundMatchingIPLDErrNotFound{msg: msg}, true
}

View File

@ -16,7 +16,7 @@ var randomSha256MH = mh.Multihash{0x12, 0x20, 0x88, 0x82, 0x73, 0x37, 0x7c, 0xc1
func doParseIpldNotFoundTest(t *testing.T, original error) {
originalMsg := original.Error()
rebuilt := parseIPLDNotFoundWithFallbackToMSG(originalMsg)
rebuilt := parseErrNotFoundWithFallbackToMSG(originalMsg)
rebuiltMsg := rebuilt.Error()
@ -32,7 +32,7 @@ func doParseIpldNotFoundTest(t *testing.T, original error) {
}
func TestParseIPLDNotFound(t *testing.T) {
if err := parseIPLDNotFoundWithFallbackToMSG(""); err != nil {
if err := parseErrNotFoundWithFallbackToMSG(""); err != nil {
t.Errorf("expected empty string to give no error; got %T %q", err, err.Error())
}
@ -59,6 +59,27 @@ func TestParseIPLDNotFound(t *testing.T) {
}
}
func TestBlockstoreNotFoundMatchingIPLDErrNotFound(t *testing.T) {
if !ipld.IsNotFound(blockstoreNotFoundMatchingIPLDErrNotFound{}) {
t.Fatalf("expected blockstoreNotFoundMatchingIPLDErrNotFound to match ipld.IsNotFound; got false")
}
for _, wrap := range [...]string{
"",
"merkledag: %w",
"testing: %w the test",
"%w is wrong",
} {
var err error = blockstoreNotFoundMatchingIPLDErrNotFound{"blockstore: block not found"}
if wrap != "" {
err = fmt.Errorf(wrap, err)
}
doParseIpldNotFoundTest(t, err)
}
}
func TestNotAsciiLetterOrDigits(t *testing.T) {
for i := rune(0); i <= 256; i++ {
if notAsciiLetterOrDigits(i) != !strings.ContainsAny(string(i), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") {