@@ -3,9 +3,10 @@ package httpapi
3
3
import (
4
4
"context"
5
5
"encoding/json"
6
+ "strings"
6
7
7
8
"github.com/ipfs/go-cid"
8
- "github.com/ipfs/interface-go-ipfs-core"
9
+ iface "github.com/ipfs/interface-go-ipfs-core"
9
10
caopts "github.com/ipfs/interface-go-ipfs-core/options"
10
11
"github.com/ipfs/interface-go-ipfs-core/path"
11
12
"github.com/pkg/errors"
@@ -24,6 +25,11 @@ type pinRefKeyList struct {
24
25
type pin struct {
25
26
path path.Resolved
26
27
typ string
28
+ err error
29
+ }
30
+
31
+ func (p * pin ) Err () error {
32
+ return p .err
27
33
}
28
34
29
35
func (p * pin ) Path () path.Resolved {
@@ -44,7 +50,7 @@ func (api *PinAPI) Add(ctx context.Context, p path.Path, opts ...caopts.PinAddOp
44
50
Option ("recursive" , options .Recursive ).Exec (ctx , nil )
45
51
}
46
52
47
- func (api * PinAPI ) Ls (ctx context.Context , opts ... caopts.PinLsOption ) ([] iface.Pin , error ) {
53
+ func (api * PinAPI ) Ls (ctx context.Context , opts ... caopts.PinLsOption ) (<- chan iface.Pin , error ) {
48
54
options , err := caopts .PinLsOptions (opts ... )
49
55
if err != nil {
50
56
return nil , err
@@ -57,16 +63,46 @@ func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) ([]iface.
57
63
return nil , err
58
64
}
59
65
60
- pins := make ([]iface.Pin , 0 , len (out .Keys ))
61
- for hash , p := range out .Keys {
62
- c , err := cid .Parse (hash )
63
- if err != nil {
64
- return nil , err
66
+ pins := make (chan iface.Pin )
67
+ go func (ch chan <- iface.Pin ) {
68
+ defer close (ch )
69
+ for hash , p := range out .Keys {
70
+ c , e := cid .Parse (hash )
71
+ if e != nil {
72
+ ch <- & pin {typ : p .Type , err : e }
73
+ return
74
+ }
75
+ ch <- & pin {typ : p .Type , path : path .IpldPath (c ), err : e }
65
76
}
66
- pins = append (pins , & pin {typ : p .Type , path : path .IpldPath (c )})
77
+ }(pins )
78
+ return pins , nil
79
+ }
80
+
81
+ // IsPinned returns whether or not the given cid is pinned
82
+ // and an explanation of why its pinned
83
+ func (api * PinAPI ) IsPinned (ctx context.Context , p path.Path , opts ... caopts.PinIsPinnedOption ) (string , bool , error ) {
84
+ options , err := caopts .PinIsPinnedOptions (opts ... )
85
+ if err != nil {
86
+ return "" , false , err
87
+ }
88
+ var out pinRefKeyList
89
+ err = api .core ().Request ("pin/ls" ).
90
+ Option ("type" , options .WithType ).
91
+ Option ("arg" , p .String ()).
92
+ Exec (ctx , & out )
93
+ if err != nil {
94
+ // TODO: This error-type discrimination based on sub-string matching is brittle.
95
+ // It is addressed by this open issue: https://github.com/ipfs/go-ipfs/issues/7563
96
+ if strings .Index (err .Error (), "is not pinned" ) != - 1 {
97
+ return "" , false , nil
98
+ }
99
+ return "" , false , err
67
100
}
68
101
69
- return pins , nil
102
+ for _ , obj := range out .Keys {
103
+ return obj .Type , true , nil
104
+ }
105
+ return "" , false , errors .New ("http api returned no error and no results" )
70
106
}
71
107
72
108
func (api * PinAPI ) Rm (ctx context.Context , p path.Path , opts ... caopts.PinRmOption ) error {
0 commit comments