feat: add blockstore: block not found matching too
This commit was moved from ipfs/go-ipfs-http-client@a3354f062c97bcb6412e74ecfb24e84208edc479
Jorropo committed
Apr 1, 2022 at 00:23 UTC
775bcb7f09de0d13a64b013ccaefa253e44c3403
3 files changed
+76
-11
client/httpapi/block.go
+3
-3
@@ -66,7 +66,7 @@ func (api *BlockAPI) Get(ctx context.Context, p path.Path) (io.Reader, error) {
66
return nil, err
67
}
68
if resp.Error != nil {
69
- return nil, parseIPLDNotFoundWithFallbackToError(resp.Error)
69
+ return nil, parseErrNotFoundWithFallbackToError(resp.Error)
70
}
71
72
//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
98
return err
99
}
100
101
- return parseIPLDNotFoundWithFallbackToMSG(removedBlock.Error)
101
+ return parseErrNotFoundWithFallbackToMSG(removedBlock.Error)
102
}
103
104
func (api *BlockAPI) Stat(ctx context.Context, p path.Path) (iface.BlockStat, error) {
105
var out blockStat
106
err := api.core().Request("block/stat", p.String()).Exec(ctx, &out)
107
if err != nil {
108
- return nil, parseIPLDNotFoundWithFallbackToError(err)
108
+ return nil, parseErrNotFoundWithFallbackToError(err)
109
}
110
out.cid, err = cid.Parse(out.Key)
111
if err != nil {
client/httpapi/errors.go
+50
-6
@@ -8,6 +8,8 @@ import (
8
ipld "github.com/ipfs/go-ipld-format"
9
)
10
11
+// This file handle parsing and returning the correct ABI based errors from error messages
12
+
13
type prePostWrappedNotFoundError struct {
14
pre string
15
post string
@@ -27,8 +29,8 @@ func (e prePostWrappedNotFoundError) Unwrap() error {
29
return e.wrapped
30
}
31
30
-func parseIPLDNotFoundWithFallbackToMSG(msg string) error {
31
- err, handled := parseIPLDNotFound(msg)
32
+func parseErrNotFoundWithFallbackToMSG(msg string) error {
33
+ err, handled := parseErrNotFound(msg)
34
if handled {
35
return err
36
}
@@ -36,8 +38,8 @@ func parseIPLDNotFoundWithFallbackToMSG(msg string) error {
38
return errors.New(msg)
39
}
40
39
-func parseIPLDNotFoundWithFallbackToError(msg error) error {
40
- err, handled := parseIPLDNotFound(msg.Error())
41
+func parseErrNotFoundWithFallbackToError(msg error) error {
42
+ err, handled := parseErrNotFound(msg.Error())
43
if handled {
44
return err
45
}
@@ -57,13 +59,25 @@ func notAsciiLetterOrDigits(r rune) bool {
59
return notAsciiLetterOrDigitsLUT[r] > 0
60
}
61
60
-// This file handle parsing and returning the correct ABI based errors from error messages
62
//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
62
-func parseIPLDNotFound(msg string) (error, bool) {
63
+func parseErrNotFound(msg string) (error, bool) {
64
if msg == "" {
65
return nil, true // Fast path
66
}
67
68
+ if err, handled := parseIPLDErrNotFound(msg); handled {
69
+ return err, true
70
+ }
71
+
72
+ if err, handled := parseBlockstoreNotFound(msg); handled {
73
+ return err, true
74
+ }
75
+
76
+ return nil, false
77
+}
78
+
79
+//lint:ignore ST1008 using error as values
80
+func parseIPLDErrNotFound(msg string) (error, bool) {
81
// The patern we search for is:
82
const ipldErrNotFoundKey = "ipld: could not find " /*CID*/
83
// 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) {
128
129
return err, true
130
}
131
+
132
+// This is a simple error type that just return msg as Error().
133
+// But that also match ipld.ErrNotFound when called with Is(err).
134
+// That is needed to keep compatiblity with code that use string.Contains(err.Error(), "blockstore: block not found")
135
+// and code using ipld.ErrNotFound
136
+type blockstoreNotFoundMatchingIPLDErrNotFound struct {
137
+ msg string
138
+}
139
+
140
+func (e blockstoreNotFoundMatchingIPLDErrNotFound) String() string {
141
+ return e.Error()
142
+}
143
+
144
+func (e blockstoreNotFoundMatchingIPLDErrNotFound) Error() string {
145
+ return e.msg
146
+}
147
+
148
+func (e blockstoreNotFoundMatchingIPLDErrNotFound) Is(err error) bool {
149
+ _, ok := err.(ipld.ErrNotFound)
150
+ return ok
151
+}
152
+
153
+//lint:ignore ST1008 using error as values
154
+func parseBlockstoreNotFound(msg string) (error, bool) {
155
+ if !strings.Contains(msg, "blockstore: block not found") {
156
+ return nil, false
157
+ }
158
+
159
+ return blockstoreNotFoundMatchingIPLDErrNotFound{msg: msg}, true
160
+}
client/httpapi/errors_test.go
+23
-2
@@ -16,7 +16,7 @@ var randomSha256MH = mh.Multihash{0x12, 0x20, 0x88, 0x82, 0x73, 0x37, 0x7c, 0xc1
16
func doParseIpldNotFoundTest(t *testing.T, original error) {
17
originalMsg := original.Error()
18
19
- rebuilt := parseIPLDNotFoundWithFallbackToMSG(originalMsg)
19
+ rebuilt := parseErrNotFoundWithFallbackToMSG(originalMsg)
20
21
rebuiltMsg := rebuilt.Error()
22
@@ -32,7 +32,7 @@ func doParseIpldNotFoundTest(t *testing.T, original error) {
32
}
33
34
func TestParseIPLDNotFound(t *testing.T) {
35
- if err := parseIPLDNotFoundWithFallbackToMSG(""); err != nil {
35
+ if err := parseErrNotFoundWithFallbackToMSG(""); err != nil {
36
t.Errorf("expected empty string to give no error; got %T %q", err, err.Error())
37
}
38
@@ -59,6 +59,27 @@ func TestParseIPLDNotFound(t *testing.T) {
59
}
60
}
61
62
+func TestBlockstoreNotFoundMatchingIPLDErrNotFound(t *testing.T) {
63
+ if !ipld.IsNotFound(blockstoreNotFoundMatchingIPLDErrNotFound{}) {
64
+ t.Fatalf("expected blockstoreNotFoundMatchingIPLDErrNotFound to match ipld.IsNotFound; got false")
65
+ }
66
+
67
+ for _, wrap := range [...]string{
68
+ "",
69
+ "merkledag: %w",
70
+ "testing: %w the test",
71
+ "%w is wrong",
72
+ } {
73
+ var err error = blockstoreNotFoundMatchingIPLDErrNotFound{"blockstore: block not found"}
74
+
75
+ if wrap != "" {
76
+ err = fmt.Errorf(wrap, err)
77
+ }
78
+
79
+ doParseIpldNotFoundTest(t, err)
80
+ }
81
+}
82
+
83
func TestNotAsciiLetterOrDigits(t *testing.T) {
84
for i := rune(0); i <= 256; i++ {
85
if notAsciiLetterOrDigits(i) != !strings.ContainsAny(string(i), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") {