Skip to content

Commit 224d6a3

Browse files
authored
refactor(cmds): do not return errors embedded in result type (#10527)
incl. ipfs/boxo#738
1 parent 53e793a commit 224d6a3

File tree

19 files changed

+408
-341
lines changed

19 files changed

+408
-341
lines changed

client/rpc/pin.go

+25-39
Original file line numberDiff line numberDiff line change
@@ -62,59 +62,45 @@ type pinLsObject struct {
6262
Type string
6363
}
6464

65-
func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) (<-chan iface.Pin, error) {
65+
func (api *PinAPI) Ls(ctx context.Context, pins chan<- iface.Pin, opts ...caopts.PinLsOption) error {
66+
defer close(pins)
67+
6668
options, err := caopts.PinLsOptions(opts...)
6769
if err != nil {
68-
return nil, err
70+
return err
6971
}
7072

7173
res, err := api.core().Request("pin/ls").
7274
Option("type", options.Type).
7375
Option("stream", true).
7476
Send(ctx)
7577
if err != nil {
76-
return nil, err
78+
return err
7779
}
78-
79-
pins := make(chan iface.Pin)
80-
go func(ch chan<- iface.Pin) {
81-
defer res.Output.Close()
82-
defer close(ch)
83-
84-
dec := json.NewDecoder(res.Output)
85-
var out pinLsObject
86-
for {
87-
switch err := dec.Decode(&out); err {
88-
case nil:
89-
case io.EOF:
90-
return
91-
default:
92-
select {
93-
case ch <- pin{err: err}:
94-
return
95-
case <-ctx.Done():
96-
return
97-
}
80+
defer res.Output.Close()
81+
82+
dec := json.NewDecoder(res.Output)
83+
var out pinLsObject
84+
for {
85+
err := dec.Decode(&out)
86+
if err != nil {
87+
if err != io.EOF {
88+
return err
9889
}
90+
return nil
91+
}
9992

100-
c, err := cid.Parse(out.Cid)
101-
if err != nil {
102-
select {
103-
case ch <- pin{err: err}:
104-
return
105-
case <-ctx.Done():
106-
return
107-
}
108-
}
93+
c, err := cid.Parse(out.Cid)
94+
if err != nil {
95+
return err
96+
}
10997

110-
select {
111-
case ch <- pin{typ: out.Type, name: out.Name, path: path.FromCid(c)}:
112-
case <-ctx.Done():
113-
return
114-
}
98+
select {
99+
case pins <- pin{typ: out.Type, name: out.Name, path: path.FromCid(c)}:
100+
case <-ctx.Done():
101+
return ctx.Err()
115102
}
116-
}(pins)
117-
return pins, nil
103+
}
118104
}
119105

120106
// IsPinned returns whether or not the given cid is pinned

client/rpc/unixfs.go

+48-68
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,12 @@ type lsOutput struct {
144144
Objects []lsObject
145145
}
146146

147-
func (api *UnixfsAPI) Ls(ctx context.Context, p path.Path, opts ...caopts.UnixfsLsOption) (<-chan iface.DirEntry, error) {
147+
func (api *UnixfsAPI) Ls(ctx context.Context, p path.Path, out chan<- iface.DirEntry, opts ...caopts.UnixfsLsOption) error {
148+
defer close(out)
149+
148150
options, err := caopts.UnixfsLsOptions(opts...)
149151
if err != nil {
150-
return nil, err
152+
return err
151153
}
152154

153155
resp, err := api.core().Request("ls", p.String()).
@@ -156,86 +158,64 @@ func (api *UnixfsAPI) Ls(ctx context.Context, p path.Path, opts ...caopts.Unixfs
156158
Option("stream", true).
157159
Send(ctx)
158160
if err != nil {
159-
return nil, err
161+
return err
160162
}
161163
if resp.Error != nil {
162-
return nil, resp.Error
164+
return err
163165
}
166+
defer resp.Close()
164167

165168
dec := json.NewDecoder(resp.Output)
166-
out := make(chan iface.DirEntry)
167-
168-
go func() {
169-
defer resp.Close()
170-
defer close(out)
171-
172-
for {
173-
var link lsOutput
174-
if err := dec.Decode(&link); err != nil {
175-
if err == io.EOF {
176-
return
177-
}
178-
select {
179-
case out <- iface.DirEntry{Err: err}:
180-
case <-ctx.Done():
181-
}
182-
return
183-
}
184169

185-
if len(link.Objects) != 1 {
186-
select {
187-
case out <- iface.DirEntry{Err: errors.New("unexpected Objects len")}:
188-
case <-ctx.Done():
189-
}
190-
return
170+
for {
171+
var link lsOutput
172+
if err = dec.Decode(&link); err != nil {
173+
if err != io.EOF {
174+
return err
191175
}
176+
return nil
177+
}
192178

193-
if len(link.Objects[0].Links) != 1 {
194-
select {
195-
case out <- iface.DirEntry{Err: errors.New("unexpected Links len")}:
196-
case <-ctx.Done():
197-
}
198-
return
199-
}
179+
if len(link.Objects) != 1 {
180+
return errors.New("unexpected Objects len")
181+
}
200182

201-
l0 := link.Objects[0].Links[0]
183+
if len(link.Objects[0].Links) != 1 {
184+
return errors.New("unexpected Links len")
185+
}
202186

203-
c, err := cid.Decode(l0.Hash)
204-
if err != nil {
205-
select {
206-
case out <- iface.DirEntry{Err: err}:
207-
case <-ctx.Done():
208-
}
209-
return
210-
}
187+
l0 := link.Objects[0].Links[0]
211188

212-
var ftype iface.FileType
213-
switch l0.Type {
214-
case unixfs.TRaw, unixfs.TFile:
215-
ftype = iface.TFile
216-
case unixfs.THAMTShard, unixfs.TDirectory, unixfs.TMetadata:
217-
ftype = iface.TDirectory
218-
case unixfs.TSymlink:
219-
ftype = iface.TSymlink
220-
}
189+
c, err := cid.Decode(l0.Hash)
190+
if err != nil {
191+
return err
192+
}
221193

222-
select {
223-
case out <- iface.DirEntry{
224-
Name: l0.Name,
225-
Cid: c,
226-
Size: l0.Size,
227-
Type: ftype,
228-
Target: l0.Target,
229-
230-
Mode: l0.Mode,
231-
ModTime: l0.ModTime,
232-
}:
233-
case <-ctx.Done():
234-
}
194+
var ftype iface.FileType
195+
switch l0.Type {
196+
case unixfs.TRaw, unixfs.TFile:
197+
ftype = iface.TFile
198+
case unixfs.THAMTShard, unixfs.TDirectory, unixfs.TMetadata:
199+
ftype = iface.TDirectory
200+
case unixfs.TSymlink:
201+
ftype = iface.TSymlink
235202
}
236-
}()
237203

238-
return out, nil
204+
select {
205+
case out <- iface.DirEntry{
206+
Name: l0.Name,
207+
Cid: c,
208+
Size: l0.Size,
209+
Type: ftype,
210+
Target: l0.Target,
211+
212+
Mode: l0.Mode,
213+
ModTime: l0.ModTime,
214+
}:
215+
case <-ctx.Done():
216+
return ctx.Err()
217+
}
218+
}
239219
}
240220

241221
func (api *UnixfsAPI) core() *HttpApi {

cmd/ipfs/kubo/pinmfs.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ func pinMFS(ctx context.Context, node pinMFSNode, cid cid.Cid, svcName string, s
183183

184184
// check if MFS pin exists (across all possible states) and inspect its CID
185185
pinStatuses := []pinclient.Status{pinclient.StatusQueued, pinclient.StatusPinning, pinclient.StatusPinned, pinclient.StatusFailed}
186-
lsPinCh, lsErrCh := c.Ls(ctx, pinclient.PinOpts.FilterName(pinName), pinclient.PinOpts.FilterStatus(pinStatuses...))
186+
lsPinCh, lsErrCh := c.GoLs(ctx, pinclient.PinOpts.FilterName(pinName), pinclient.PinOpts.FilterStatus(pinStatuses...))
187187
existingRequestID := "" // is there any pre-existing MFS pin with pinName (for any CID)?
188188
pinning := false // is CID for current MFS already being pinned?
189189
pinTime := time.Now().UTC()

core/commands/ls.go

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package commands
22

33
import (
4+
"context"
45
"fmt"
56
"io"
67
"os"
@@ -133,23 +134,24 @@ The JSON output contains type information.
133134
}
134135
}
135136

137+
lsCtx, cancel := context.WithCancel(req.Context)
138+
defer cancel()
139+
136140
for i, fpath := range paths {
137141
pth, err := cmdutils.PathOrCidPath(fpath)
138142
if err != nil {
139143
return err
140144
}
141145

142-
results, err := api.Unixfs().Ls(req.Context, pth,
143-
options.Unixfs.ResolveChildren(resolveSize || resolveType))
144-
if err != nil {
145-
return err
146-
}
146+
results := make(chan iface.DirEntry)
147+
lsErr := make(chan error, 1)
148+
go func() {
149+
lsErr <- api.Unixfs().Ls(lsCtx, pth, results,
150+
options.Unixfs.ResolveChildren(resolveSize || resolveType))
151+
}()
147152

148153
processLink, dirDone = processDir()
149154
for link := range results {
150-
if link.Err != nil {
151-
return link.Err
152-
}
153155
var ftype unixfs_pb.Data_DataType
154156
switch link.Type {
155157
case iface.TFile:
@@ -170,10 +172,13 @@ The JSON output contains type information.
170172
Mode: link.Mode,
171173
ModTime: link.ModTime,
172174
}
173-
if err := processLink(paths[i], lsLink); err != nil {
175+
if err = processLink(paths[i], lsLink); err != nil {
174176
return err
175177
}
176178
}
179+
if err = <-lsErr; err != nil {
180+
return err
181+
}
177182
dirDone(i)
178183
}
179184
return done()

core/commands/pin/pin.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -557,15 +557,16 @@ func pinLsAll(req *cmds.Request, typeStr string, detailed bool, name string, api
557557
panic("unhandled pin type")
558558
}
559559

560-
pins, err := api.Pin().Ls(req.Context, opt, options.Pin.Ls.Detailed(detailed), options.Pin.Ls.Name(name))
561-
if err != nil {
562-
return err
563-
}
560+
pins := make(chan coreiface.Pin)
561+
lsErr := make(chan error, 1)
562+
lsCtx, cancel := context.WithCancel(req.Context)
563+
defer cancel()
564+
565+
go func() {
566+
lsErr <- api.Pin().Ls(lsCtx, pins, opt, options.Pin.Ls.Detailed(detailed), options.Pin.Ls.Name(name))
567+
}()
564568

565569
for p := range pins {
566-
if err := p.Err(); err != nil {
567-
return err
568-
}
569570
err = emit(PinLsOutputWrapper{
570571
PinLsObject: PinLsObject{
571572
Type: p.Type(),
@@ -577,8 +578,7 @@ func pinLsAll(req *cmds.Request, typeStr string, detailed bool, name string, api
577578
return err
578579
}
579580
}
580-
581-
return nil
581+
return <-lsErr
582582
}
583583

584584
const (

0 commit comments

Comments
 (0)