commands: Refactored Command#Run function signature to (req Request, res Response)
Matt Bell committed
Jan 20, 2015 at 17:58 UTC
7b4de230eb3d33c503f7b42211c9ffd2b337a38f
27 files changed
+426
-236
cmd/ipfs/daemon.go
+26
-12
@@ -47,13 +47,14 @@ the daemon.
47
Run: daemonFunc,
48
}
49
50
-func daemonFunc(req cmds.Request) (interface{}, error) {
50
+func daemonFunc(req cmds.Request, res cmds.Response) {
51
52
// first, whether user has provided the initialization flag. we may be
53
// running in an uninitialized state.
54
initialize, _, err := req.Option(initOptionKwd).Bool()
55
if err != nil {
56
- return nil, err
56
+ res.SetError(err, cmds.ErrNormal)
57
+ return
58
}
59
if initialize {
60
@@ -64,7 +65,8 @@ func daemonFunc(req cmds.Request) (interface{}, error) {
65
if !util.FileExists(req.Context().ConfigRoot) {
66
err := initWithDefaults(req.Context().ConfigRoot)
67
if err != nil {
67
- return nil, debugerror.Wrap(err)
68
+ res.SetError(debugerror.Wrap(err), cmds.ErrNormal)
69
+ return
70
}
71
}
72
}
@@ -77,14 +79,16 @@ func daemonFunc(req cmds.Request) (interface{}, error) {
79
ctx := req.Context()
80
cfg, err := ctx.GetConfig()
81
if err != nil {
80
- return nil, err
82
+ res.SetError(err, cmds.ErrNormal)
83
+ return
84
}
85
86
// acquire the repo lock _before_ constructing a node. we need to make
87
// sure we are permitted to access the resources (datastore, etc.)
88
repo := fsrepo.At(req.Context().ConfigRoot)
89
if err := repo.Open(); err != nil {
87
- return nil, debugerror.Errorf("Couldn't obtain lock. Is another daemon already running?")
90
+ res.SetError(debugerror.Errorf("Couldn't obtain lock. Is another daemon already running?"), cmds.ErrNormal)
91
+ return
92
}
93
defer repo.Close()
94
@@ -93,13 +97,15 @@ func daemonFunc(req cmds.Request) (interface{}, error) {
97
ctx.Online = true
98
node, err := ctx.GetNode()
99
if err != nil {
96
- return nil, err
100
+ res.SetError(err, cmds.ErrNormal)
101
+ return
102
}
103
104
// verify api address is valid multiaddr
105
apiMaddr, err := ma.NewMultiaddr(cfg.Addresses.API)
106
if err != nil {
102
- return nil, err
107
+ res.SetError(err, cmds.ErrNormal)
108
+ return
109
}
110
111
var gatewayMaddr ma.Multiaddr
@@ -115,12 +121,14 @@ func daemonFunc(req cmds.Request) (interface{}, error) {
121
// mount if the user provided the --mount flag
122
mount, _, err := req.Option(mountKwd).Bool()
123
if err != nil {
118
- return nil, err
124
+ res.SetError(err, cmds.ErrNormal)
125
+ return
126
}
127
if mount {
128
fsdir, found, err := req.Option(ipfsMountKwd).String()
129
if err != nil {
123
- return nil, err
130
+ res.SetError(err, cmds.ErrNormal)
131
+ return
132
}
133
if !found {
134
fsdir = cfg.Mounts.IPFS
@@ -128,7 +136,8 @@ func daemonFunc(req cmds.Request) (interface{}, error) {
136
137
nsdir, found, err := req.Option(ipnsMountKwd).String()
138
if err != nil {
131
- return nil, err
139
+ res.SetError(err, cmds.ErrNormal)
140
+ return
141
}
142
if !found {
143
nsdir = cfg.Mounts.IPNS
@@ -136,7 +145,8 @@ func daemonFunc(req cmds.Request) (interface{}, error) {
145
146
err = commands.Mount(node, fsdir, nsdir)
147
if err != nil {
139
- return nil, err
148
+ res.SetError(err, cmds.ErrNormal)
149
+ return
150
}
151
fmt.Printf("IPFS mounted at: %s\n", fsdir)
152
fmt.Printf("IPNS mounted at: %s\n", nsdir)
@@ -156,5 +166,9 @@ func daemonFunc(req cmds.Request) (interface{}, error) {
166
corehttp.WebUIOption,
167
corehttp.GatewayOption,
168
}
159
- return nil, corehttp.ListenAndServe(node, apiMaddr, opts...)
169
+ err = corehttp.ListenAndServe(node, apiMaddr, opts...)
170
+ if err != nil {
171
+ res.SetError(err, cmds.ErrNormal)
172
+ return
173
+ }
174
}
cmd/ipfs/init.go
+11
-4
@@ -39,22 +39,29 @@ var initCmd = &cmds.Command{
39
// name of the file?
40
// TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs"),
41
},
42
- Run: func(req cmds.Request) (interface{}, error) {
42
+ Run: func(req cmds.Request, res cmds.Response) {
43
44
force, _, err := req.Option("f").Bool() // if !found, it's okay force == false
45
if err != nil {
46
- return nil, err
46
+ res.SetError(err, cmds.ErrNormal)
47
+ return
48
}
49
50
nBitsForKeypair, bitsOptFound, err := req.Option("b").Int()
51
if err != nil {
51
- return nil, err
52
+ res.SetError(err, cmds.ErrNormal)
53
+ return
54
}
55
if !bitsOptFound {
56
nBitsForKeypair = nBitsForKeypairDefault
57
}
58
57
- return doInit(req.Context().ConfigRoot, force, nBitsForKeypair)
59
+ output, err := doInit(req.Context().ConfigRoot, force, nBitsForKeypair)
60
+ if err != nil {
61
+ res.SetError(err, cmds.ErrNormal)
62
+ return
63
+ }
64
+ res.SetOutput(output)
65
},
66
}
67
cmd/ipfs/tour.go
+21
-17
@@ -36,11 +36,12 @@ IPFS very quickly. To start, run:
36
Run: tourRunFunc,
37
}
38
39
-func tourRunFunc(req cmds.Request) (interface{}, error) {
39
+func tourRunFunc(req cmds.Request, res cmds.Response) {
40
41
cfg, err := req.Context().GetConfig()
42
if err != nil {
43
- return nil, err
43
+ res.SetError(err, cmds.ErrNormal)
44
+ return
45
}
46
47
id := tour.TopicID(cfg.Tour.Last)
@@ -64,11 +65,10 @@ func tourRunFunc(req cmds.Request) (interface{}, error) {
65
fmt.Fprintln(&w, "")
66
fprintTourList(&w, tour.TopicID(cfg.Tour.Last))
67
67
- return nil, nil
68
+ return
69
}
70
71
fprintTourShow(&w, t)
71
- return nil, nil
72
}
73
74
var cmdIpfsTourNext = &cmds.Command{
@@ -76,21 +76,24 @@ var cmdIpfsTourNext = &cmds.Command{
76
Tagline: "Show the next IPFS Tour topic",
77
},
78
79
- Run: func(req cmds.Request) (interface{}, error) {
79
+ Run: func(req cmds.Request, res cmds.Response) {
80
var w bytes.Buffer
81
path := req.Context().ConfigRoot
82
cfg, err := req.Context().GetConfig()
83
if err != nil {
84
- return nil, err
84
+ res.SetError(err, cmds.ErrNormal)
85
+ return
86
}
87
88
id := tour.NextTopic(tour.TopicID(cfg.Tour.Last))
89
topic, err := tourGet(id)
90
if err != nil {
90
- return nil, err
91
+ res.SetError(err, cmds.ErrNormal)
92
+ return
93
}
94
if err := fprintTourShow(&w, topic); err != nil {
93
- return nil, err
95
+ res.SetError(err, cmds.ErrNormal)
96
+ return
97
}
98
99
// topic changed, not last. write it out.
@@ -98,12 +101,12 @@ var cmdIpfsTourNext = &cmds.Command{
101
cfg.Tour.Last = string(id)
102
err := writeConfig(path, cfg)
103
if err != nil {
101
- return nil, err
104
+ res.SetError(err, cmds.ErrNormal)
105
+ return
106
}
107
}
108
109
w.WriteTo(os.Stdout)
106
- return nil, nil
110
},
111
}
112
@@ -112,19 +115,20 @@ var cmdIpfsTourRestart = &cmds.Command{
115
Tagline: "Restart the IPFS Tour",
116
},
117
115
- Run: func(req cmds.Request) (interface{}, error) {
118
+ Run: func(req cmds.Request, res cmds.Response) {
119
path := req.Context().ConfigRoot
120
cfg, err := req.Context().GetConfig()
121
if err != nil {
119
- return nil, err
122
+ res.SetError(err, cmds.ErrNormal)
123
+ return
124
}
125
126
cfg.Tour.Last = ""
127
err = writeConfig(path, cfg)
128
if err != nil {
125
- return nil, err
129
+ res.SetError(err, cmds.ErrNormal)
130
+ return
131
}
127
- return nil, nil
132
},
133
}
134
@@ -133,16 +137,16 @@ var cmdIpfsTourList = &cmds.Command{
137
Tagline: "Show a list of IPFS Tour topics",
138
},
139
136
- Run: func(req cmds.Request) (interface{}, error) {
140
+ Run: func(req cmds.Request, res cmds.Response) {
141
cfg, err := req.Context().GetConfig()
142
if err != nil {
139
- return nil, err
143
+ res.SetError(err, cmds.ErrNormal)
144
+ return
145
}
146
147
var w bytes.Buffer
148
fprintTourList(&w, tour.TopicID(cfg.Tour.Last))
149
w.WriteTo(os.Stdout)
145
- return nil, nil
150
},
151
}
152
commands/command.go
+4
-14
@@ -14,7 +14,7 @@ var log = u.Logger("command")
14
15
// Function is the type of function that Commands use.
16
// It reads from the Request, and writes results to the Response.
17
-type Function func(Request) (interface{}, error)
17
+type Function func(Request, Response)
18
19
// Marshaler is a function that takes in a Response, and returns an io.Reader
20
// (or an error on failure)
@@ -95,21 +95,12 @@ func (c *Command) Call(req Request) Response {
95
return res
96
}
97
98
- output, err := cmd.Run(req)
99
- if err != nil {
100
- // if returned error is a commands.Error, use its error code
101
- // otherwise, just default the code to ErrNormal
102
- switch e := err.(type) {
103
- case *Error:
104
- res.SetError(e, e.Code)
105
- case Error:
106
- res.SetError(e, e.Code)
107
- default:
108
- res.SetError(err, ErrNormal)
109
- }
98
+ cmd.Run(req, res)
99
+ if res.Error() != nil {
100
return res
101
}
102
103
+ output := res.Output()
104
isChan := false
105
actualType := reflect.TypeOf(output)
106
if actualType != nil {
@@ -140,7 +131,6 @@ func (c *Command) Call(req Request) Response {
131
}
132
}
133
143
- res.SetOutput(output)
134
return res
135
}
136
commands/command_test.go
+2
-2
@@ -2,8 +2,8 @@ package commands
2
3
import "testing"
4
5
-func noop(req Request) (interface{}, error) {
6
- return nil, nil
5
+func noop(req Request, res Response) {
6
+ return
7
}
8
9
func TestOptionValidation(t *testing.T) {
core/commands/add.go
+4
-4
@@ -44,13 +44,15 @@ remains to be implemented.
44
cmds.OptionRecursivePath, // a builtin option that allows recursive paths (-r, --recursive)
45
cmds.BoolOption("quiet", "q", "Write minimal output"),
46
},
47
- Run: func(req cmds.Request) (interface{}, error) {
47
+ Run: func(req cmds.Request, res cmds.Response) {
48
n, err := req.Context().GetNode()
49
if err != nil {
50
- return nil, err
50
+ res.SetError(err, cmds.ErrNormal)
51
+ return
52
}
53
54
outChan := make(chan interface{})
55
+ res.SetOutput((<-chan interface{})(outChan))
56
57
go func() {
58
defer close(outChan)
@@ -67,8 +69,6 @@ remains to be implemented.
69
}
70
}
71
}()
70
-
71
- return outChan, nil
72
},
73
Marshalers: cmds.MarshalerMap{
74
cmds.Text: func(res cmds.Response) (io.Reader, error) {
core/commands/block.go
+25
-16
@@ -2,6 +2,7 @@ package commands
2
3
import (
4
"bytes"
5
+ "errors"
6
"fmt"
7
"io"
8
"io/ioutil"
@@ -57,16 +58,17 @@ on raw ipfs blocks. It outputs the following to stdout:
58
Arguments: []cmds.Argument{
59
cmds.StringArg("key", true, false, "The base58 multihash of an existing block to get").EnableStdin(),
60
},
60
- Run: func(req cmds.Request) (interface{}, error) {
61
+ Run: func(req cmds.Request, res cmds.Response) {
62
b, err := getBlockForKey(req, req.Arguments()[0])
63
if err != nil {
63
- return nil, err
64
+ res.SetError(err, cmds.ErrNormal)
65
+ return
66
}
67
66
- return &BlockStat{
68
+ res.SetOutput(&BlockStat{
69
Key: b.Key().Pretty(),
70
Size: len(b.Data),
69
- }, nil
71
+ })
72
},
73
Type: BlockStat{},
74
Marshalers: cmds.MarshalerMap{
@@ -89,13 +91,14 @@ It outputs to stdout, and <key> is a base58 encoded multihash.
91
Arguments: []cmds.Argument{
92
cmds.StringArg("key", true, false, "The base58 multihash of an existing block to get").EnableStdin(),
93
},
92
- Run: func(req cmds.Request) (interface{}, error) {
94
+ Run: func(req cmds.Request, res cmds.Response) {
95
b, err := getBlockForKey(req, req.Arguments()[0])
96
if err != nil {
95
- return nil, err
97
+ res.SetError(err, cmds.ErrNormal)
98
+ return
99
}
100
98
- return bytes.NewReader(b.Data), nil
101
+ res.SetOutput(bytes.NewReader(b.Data))
102
},
103
}
104
@@ -111,25 +114,29 @@ It reads from stdin, and <key> is a base58 encoded multihash.
114
Arguments: []cmds.Argument{
115
cmds.FileArg("data", true, false, "The data to be stored as an IPFS block").EnableStdin(),
116
},
114
- Run: func(req cmds.Request) (interface{}, error) {
117
+ Run: func(req cmds.Request, res cmds.Response) {
118
n, err := req.Context().GetNode()
119
if err != nil {
117
- return nil, err
120
+ res.SetError(err, cmds.ErrNormal)
121
+ return
122
}
123
124
file, err := req.Files().NextFile()
125
if err != nil {
122
- return nil, err
126
+ res.SetError(err, cmds.ErrNormal)
127
+ return
128
}
129
130
data, err := ioutil.ReadAll(file)
131
if err != nil {
127
- return nil, err
132
+ res.SetError(err, cmds.ErrNormal)
133
+ return
134
}
135
136
err = file.Close()
137
if err != nil {
132
- return nil, err
138
+ res.SetError(err, cmds.ErrNormal)
139
+ return
140
}
141
142
b := blocks.NewBlock(data)
@@ -137,13 +144,14 @@ It reads from stdin, and <key> is a base58 encoded multihash.
144
145
k, err := n.Blocks.AddBlock(b)
146
if err != nil {
140
- return nil, err
147
+ res.SetError(err, cmds.ErrNormal)
148
+ return
149
}
150
143
- return &BlockStat{
151
+ res.SetOutput(&BlockStat{
152
Key: k.String(),
153
Size: len(data),
146
- }, nil
154
+ })
155
},
156
Marshalers: cmds.MarshalerMap{
157
cmds.Text: func(res cmds.Response) (io.Reader, error) {
@@ -160,7 +168,7 @@ func getBlockForKey(req cmds.Request, key string) (*blocks.Block, error) {
168
}
169
170
if !u.IsValidHash(key) {
163
- return nil, cmds.Error{"Not a valid hash", cmds.ErrClient}
171
+ return nil, errors.New("Not a valid hash")
172
}
173
174
h, err := mh.FromB58String(key)
@@ -173,6 +181,7 @@ func getBlockForKey(req cmds.Request, key string) (*blocks.Block, error) {
181
if err != nil {
182
return nil, err
183
}
184
+
185
log.Debugf("ipfs block: got block with key: %q", b.Key())
186
return b, nil
187
}
core/commands/bootstrap.go
+33
-18
@@ -76,29 +76,33 @@ in the bootstrap list).
76
cmds.BoolOption("default", "add default bootstrap nodes"),
77
},
78
79
- Run: func(req cmds.Request) (interface{}, error) {
79
+ Run: func(req cmds.Request, res cmds.Response) {
80
inputPeers, err := config.ParseBootstrapPeers(req.Arguments())
81
if err != nil {
82
- return nil, err
82
+ res.SetError(err, cmds.ErrNormal)
83
+ return
84
}
85
86
r := fsrepo.At(req.Context().ConfigRoot)
87
if err := r.Open(); err != nil {
87
- return nil, err
88
+ res.SetError(err, cmds.ErrNormal)
89
+ return
90
}
91
defer r.Close()
92
cfg := r.Config()
93
94
deflt, _, err := req.Option("default").Bool()
95
if err != nil {
94
- return nil, err
96
+ res.SetError(err, cmds.ErrNormal)
97
+ return
98
}
99
100
if deflt {
101
// parse separately for meaningful, correct error.
102
defltPeers, err := DefaultBootstrapPeers()
103
if err != nil {
101
- return nil, err
104
+ res.SetError(err, cmds.ErrNormal)
105
+ return
106
}
107
108
inputPeers = append(inputPeers, defltPeers...)
@@ -106,14 +110,16 @@ in the bootstrap list).
110
111
added, err := bootstrapAdd(r, cfg, inputPeers)
112
if err != nil {
109
- return nil, err
113
+ res.SetError(err, cmds.ErrNormal)
114
+ return
115
}
116
117
if len(inputPeers) == 0 {
113
- return nil, cmds.ClientError("no bootstrap peers to add")
118
+ res.SetError(errors.New("no bootstrap peers to add"), cmds.ErrClient)
119
+ return
120
}
121
116
- return &BootstrapOutput{added}, nil
122
+ res.SetOutput(&BootstrapOutput{added})
123
},
124
Type: BootstrapOutput{},
125
Marshalers: cmds.MarshalerMap{
@@ -125,7 +131,11 @@ in the bootstrap list).
131
132
var buf bytes.Buffer
133
err := bootstrapWritePeers(&buf, "added ", v.Peers)
128
- return &buf, err
134
+ if err != nil {
135
+ return nil, err
136
+ }
137
+
138
+ return &buf, nil
139
},
140
},
141
}
@@ -143,22 +153,25 @@ var bootstrapRemoveCmd = &cmds.Command{
153
Options: []cmds.Option{
154
cmds.BoolOption("all", "Remove all bootstrap peers."),
155
},
146
- Run: func(req cmds.Request) (interface{}, error) {
156
+ Run: func(req cmds.Request, res cmds.Response) {
157
input, err := config.ParseBootstrapPeers(req.Arguments())
158
if err != nil {
149
- return nil, err
159
+ res.SetError(err, cmds.ErrNormal)
160
+ return
161
}
162
163
r := fsrepo.At(req.Context().ConfigRoot)
164
if err := r.Open(); err != nil {
154
- return nil, err
165
+ res.SetError(err, cmds.ErrNormal)
166
+ return
167
}
168
defer r.Close()
169
cfg := r.Config()
170
171
all, _, err := req.Option("all").Bool()
172
if err != nil {
161
- return nil, err
173
+ res.SetError(err, cmds.ErrNormal)
174
+ return
175
}
176
177
var removed []config.BootstrapPeer
@@ -168,10 +181,11 @@ var bootstrapRemoveCmd = &cmds.Command{
181
removed, err = bootstrapRemove(r, cfg, input)
182
}
183
if err != nil {
171
- return nil, err
184
+ res.SetError(err, cmds.ErrNormal)
185
+ return
186
}
187
174
- return &BootstrapOutput{removed}, nil
188
+ res.SetOutput(&BootstrapOutput{removed})
189
},
190
Type: BootstrapOutput{},
191
Marshalers: cmds.MarshalerMap{
@@ -194,14 +208,15 @@ var bootstrapListCmd = &cmds.Command{
208
ShortDescription: "Peers are output in the format '<multiaddr>/<peerID>'.",
209
},
210
197
- Run: func(req cmds.Request) (interface{}, error) {
211
+ Run: func(req cmds.Request, res cmds.Response) {
212
cfg, err := req.Context().GetConfig()
213
if err != nil {
200
- return nil, err
214
+ res.SetError(err, cmds.ErrNormal)
215
+ return
216
}
217
218
peers := cfg.Bootstrap
204
- return &BootstrapOutput{peers}, nil
219
+ res.SetOutput(&BootstrapOutput{peers})
220
},
221
Type: BootstrapOutput{},
222
Marshalers: cmds.MarshalerMap{
core/commands/cat.go
+6
-4
@@ -20,21 +20,23 @@ it contains.
20
Arguments: []cmds.Argument{
21
cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to be outputted").EnableStdin(),
22
},
23
- Run: func(req cmds.Request) (interface{}, error) {
23
+ Run: func(req cmds.Request, res cmds.Response) {
24
node, err := req.Context().GetNode()
25
if err != nil {
26
- return nil, err
26
+ res.SetError(err, cmds.ErrNormal)
27
+ return
28
}
29
30
readers := make([]io.Reader, 0, len(req.Arguments()))
31
32
readers, err = cat(node, req.Arguments())
33
if err != nil {
33
- return nil, err
34
+ res.SetError(err, cmds.ErrNormal)
35
+ return
36
}
37
38
reader := io.MultiReader(readers...)
37
- return reader, nil
39
+ res.SetOutput(reader)
40
},
41
}
42
core/commands/commands.go
+2
-2
@@ -22,9 +22,9 @@ func CommandsCmd(root *cmds.Command) *cmds.Command {
22
ShortDescription: `Lists all available commands (and subcommands) and exits.`,
23
},
24
25
- Run: func(req cmds.Request) (interface{}, error) {
25
+ Run: func(req cmds.Request, res cmds.Response) {
26
root := cmd2outputCmd("ipfs", root)
27
- return &root, nil
27
+ res.SetOutput(&root)
28
},
29
Marshalers: cmds.MarshalerMap{
30
cmds.Text: func(res cmds.Response) (io.Reader, error) {
core/commands/config.go
+42
-15
@@ -57,23 +57,34 @@ Set the value of the 'datastore.path' key:
57
cmds.StringArg("key", true, false, "The key of the config entry (e.g. \"Addresses.API\")"),
58
cmds.StringArg("value", false, false, "The value to set the config entry to"),
59
},
60
- Run: func(req cmds.Request) (interface{}, error) {
60
+ Run: func(req cmds.Request, res cmds.Response) {
61
args := req.Arguments()
62
key := args[0]
63
64
r := fsrepo.At(req.Context().ConfigRoot)
65
if err := r.Open(); err != nil {
66
- return nil, err
66
+ res.SetError(err, cmds.ErrNormal)
67
+ return
68
}
69
defer r.Close()
70
71
var value string
72
if len(args) == 2 {
73
value = args[1]
73
- return setConfig(r, key, value)
74
+ output, err := setConfig(r, key, value)
75
+ if err != nil {
76
+ res.SetError(err, cmds.ErrNormal)
77
+ return
78
+ }
79
+ res.SetOutput(output)
80
81
} else {
76
- return getConfig(r, key)
82
+ output, err := getConfig(r, key)
83
+ if err != nil {
84
+ res.SetError(err, cmds.ErrNormal)
85
+ return
86
+ }
87
+ res.SetOutput(output)
88
}
89
},
90
Marshalers: cmds.MarshalerMap{
@@ -117,13 +128,19 @@ included in the output of this command.
128
`,
129
},
130
120
- Run: func(req cmds.Request) (interface{}, error) {
131
+ Run: func(req cmds.Request, res cmds.Response) {
132
filename, err := config.Filename(req.Context().ConfigRoot)
133
if err != nil {
123
- return nil, err
134
+ res.SetError(err, cmds.ErrNormal)
135
+ return
136
}
137
126
- return showConfig(filename)
138
+ output, err := showConfig(filename)
139
+ if err != nil {
140
+ res.SetError(err, cmds.ErrNormal)
141
+ return
142
+ }
143
+ res.SetOutput(output)
144
},
145
}
146
@@ -136,19 +153,23 @@ variable set to your preferred text editor.
153
`,
154
},
155
139
- Run: func(req cmds.Request) (interface{}, error) {
156
+ Run: func(req cmds.Request, res cmds.Response) {
157
filename, err := config.Filename(req.Context().ConfigRoot)
158
if err != nil {
142
- return nil, err
159
+ res.SetError(err, cmds.ErrNormal)
160
+ return
161
}
162
145
- return nil, editConfig(filename)
163
+ err = editConfig(filename)
164
+ if err != nil {
165
+ res.SetError(err, cmds.ErrNormal)
166
+ }
167
},
168
}
169
170
var configReplaceCmd = &cmds.Command{
171
Helptext: cmds.HelpText{
151
- Tagline: "Replaces the config with <file>",
172
+ Tagline: "Replaces the config with `file>",
173
ShortDescription: `
174
Make sure to back up the config file first if neccessary, this operation
175
can't be undone.
@@ -158,20 +179,26 @@ can't be undone.
179
Arguments: []cmds.Argument{
180
cmds.FileArg("file", true, false, "The file to use as the new config"),
181
},
161
- Run: func(req cmds.Request) (interface{}, error) {
182
+ Run: func(req cmds.Request, res cmds.Response) {
183
r := fsrepo.At(req.Context().ConfigRoot)
184
if err := r.Open(); err != nil {
164
- return nil, err
185
+ res.SetError(err, cmds.ErrNormal)
186
+ return
187
}
188
defer r.Close()
189
190
file, err := req.Files().NextFile()
191
if err != nil {
170
- return nil, err
192
+ res.SetError(err, cmds.ErrNormal)
193
+ return
194
}
195
defer file.Close()
196
174
- return nil, replaceConfig(r, file)
197
+ err = replaceConfig(r, file)
198
+ if err != nil {
199
+ res.SetError(err, cmds.ErrNormal)
200
+ return
201
+ }
202
},
203
}
204
core/commands/diag.go
+26
-10
@@ -2,6 +2,7 @@ package commands
2
3
import (
4
"bytes"
5
+ "errors"
6
"io"
7
"strings"
8
"text/template"
@@ -63,50 +64,65 @@ connected peers and latencies between them.
64
cmds.StringOption("vis", "output vis. one of: "+strings.Join(visFmts, ", ")),
65
},
66
66
- Run: func(req cmds.Request) (interface{}, error) {
67
+ Run: func(req cmds.Request, res cmds.Response) {
68
n, err := req.Context().GetNode()
69
if err != nil {
69
- return nil, err
70
+ res.SetError(err, cmds.ErrNormal)
71
+ return
72
}
73
74
if !n.OnlineMode() {
73
- return nil, errNotOnline
75
+ res.SetError(errNotOnline, cmds.ErrClient)
76
+ return
77
}
78
79
vis, _, err := req.Option("vis").String()
80
if err != nil {
78
- return nil, err
81
+ res.SetError(err, cmds.ErrNormal)
82
+ return
83
}
84
85
timeoutS, _, err := req.Option("timeout").String()
86
if err != nil {
83
- return nil, err
87
+ res.SetError(err, cmds.ErrNormal)
88
+ return
89
}
90
timeout := DefaultDiagnosticTimeout
91
if timeoutS != "" {
92
t, err := time.ParseDuration(timeoutS)
93
if err != nil {
89
- return nil, cmds.ClientError("error parsing timeout")
94
+ res.SetError(errors.New("error parsing timeout"), cmds.ErrNormal)
95
+ return
96
}
97
timeout = t
98
}
99
100
info, err := n.Diagnostics.GetDiagnostic(timeout)
101
if err != nil {
96
- return nil, err
102
+ res.SetError(err, cmds.ErrNormal)
103
+ return
104
}
105
106
switch vis {
107
case visD3:
101
- return bytes.NewReader(diag.GetGraphJson(info)), nil
108
+ res.SetOutput(bytes.NewReader(diag.GetGraphJson(info)))
109
case visDot:
110
var buf bytes.Buffer
111
w := diag.DotWriter{W: &buf}
112
err := w.WriteGraph(info)
106
- return io.Reader(&buf), err
113
+ if err != nil {
114
+ res.SetError(err, cmds.ErrNormal)
115
+ return
116
+ }
117
+ res.SetOutput(io.Reader(&buf))
118
}
119
109
- return stdDiagOutputMarshal(standardDiagOutput(info))
120
+ output, err := stdDiagOutputMarshal(standardDiagOutput(info))
121
+ if err != nil {
122
+ res.SetError(err, cmds.ErrNormal)
123
+ return
124
+ }
125
+ res.SetOutput(output)
126
},
127
}
128
core/commands/id.go
+25
-8
@@ -45,37 +45,54 @@ if no peer is specified, prints out local peers info.
45
Arguments: []cmds.Argument{
46
cmds.StringArg("peerid", false, false, "peer.ID of node to look up").EnableStdin(),
47
},
48
- Run: func(req cmds.Request) (interface{}, error) {
48
+ Run: func(req cmds.Request, res cmds.Response) {
49
node, err := req.Context().GetNode()
50
if err != nil {
51
- return nil, err
51
+ res.SetError(err, cmds.ErrNormal)
52
+ return
53
}
54
55
if len(req.Arguments()) == 0 {
55
- return printPeer(node.Peerstore, node.Identity)
56
+ output, err := printPeer(node.Peerstore, node.Identity)
57
+ if err != nil {
58
+ res.SetError(err, cmds.ErrNormal)
59
+ return
60
+ }
61
+ res.SetOutput(output)
62
+ return
63
}
64
65
pid := req.Arguments()[0]
66
67
id := peer.ID(b58.Decode(pid))
68
if len(id) == 0 {
62
- return nil, cmds.ClientError("Invalid peer id")
69
+ res.SetError(cmds.ClientError("Invalid peer id"), cmds.ErrClient)
70
+ return
71
}
72
73
ctx, _ := context.WithTimeout(context.TODO(), time.Second*5)
74
// TODO handle offline mode with polymorphism instead of conditionals
75
if !node.OnlineMode() {
68
- return nil, errors.New(offlineIdErrorMessage)
76
+ res.SetError(errors.New(offlineIdErrorMessage), cmds.ErrClient)
77
+ return
78
}
79
80
p, err := node.Routing.FindPeer(ctx, id)
81
if err == kb.ErrLookupFailure {
73
- return nil, errors.New(offlineIdErrorMessage)
82
+ res.SetError(errors.New(offlineIdErrorMessage), cmds.ErrClient)
83
+ return
84
}
85
if err != nil {
76
- return nil, err
86
+ res.SetError(err, cmds.ErrNormal)
87
+ return
88
+ }
89
+
90
+ output, err := printPeer(node.Peerstore, p.ID)
91
+ if err != nil {
92
+ res.SetError(err, cmds.ErrNormal)
93
+ return
94
}
78
- return printPeer(node.Peerstore, p.ID)
95
+ res.SetOutput(output)
96
},
97
Marshalers: cmds.MarshalerMap{
98
cmds.Text: func(res cmds.Response) (io.Reader, error) {
core/commands/log.go
+6
-5
@@ -47,7 +47,7 @@ output of a running daemon.
47
cmds.StringArg("subsystem", true, false, fmt.Sprintf("the subsystem logging identifier. Use '%s' for all subsystems.", logAllKeyword)),
48
cmds.StringArg("level", true, false, "one of: debug, info, notice, warning, error, critical"),
49
},
50
- Run: func(req cmds.Request) (interface{}, error) {
50
+ Run: func(req cmds.Request, res cmds.Response) {
51
52
args := req.Arguments()
53
subsystem, level := args[0], args[1]
@@ -57,12 +57,13 @@ output of a running daemon.
57
}
58
59
if err := u.SetLogLevel(subsystem, level); err != nil {
60
- return nil, err
60
+ res.SetError(err, cmds.ErrNormal)
61
+ return
62
}
63
64
s := fmt.Sprintf("Changed log level of '%s' to '%s'", subsystem, level)
65
log.Info(s)
65
- return &MessageOutput{s}, nil
66
+ res.SetOutput(&MessageOutput{s})
67
},
68
Marshalers: cmds.MarshalerMap{
69
cmds.Text: MessageTextMarshaler,
@@ -78,7 +79,7 @@ var logTailCmd = &cmds.Command{
79
`,
80
},
81
81
- Run: func(req cmds.Request) (interface{}, error) {
82
+ Run: func(req cmds.Request, res cmds.Response) {
83
path := fmt.Sprintf("%s/logs/events.log", req.Context().ConfigRoot)
84
85
outChan := make(chan interface{})
@@ -108,7 +109,7 @@ var logTailCmd = &cmds.Command{
109
}
110
}()
111
111
- return (<-chan interface{})(outChan), nil
112
+ res.SetOutput((<-chan interface{})(outChan))
113
},
114
Marshalers: cmds.MarshalerMap{
115
cmds.Text: func(res cmds.Response) (io.Reader, error) {
core/commands/ls.go
+6
-4
@@ -37,10 +37,11 @@ it contains, with the following format:
37
Arguments: []cmds.Argument{
38
cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from").EnableStdin(),
39
},
40
- Run: func(req cmds.Request) (interface{}, error) {
40
+ Run: func(req cmds.Request, res cmds.Response) {
41
node, err := req.Context().GetNode()
42
if err != nil {
43
- return nil, err
43
+ res.SetError(err, cmds.ErrNormal)
44
+ return
45
}
46
47
paths := req.Arguments()
@@ -49,7 +50,8 @@ it contains, with the following format:
50
for _, path := range paths {
51
dagnode, err := node.Resolver.ResolvePath(path)
52
if err != nil {
52
- return nil, err
53
+ res.SetError(err, cmds.ErrNormal)
54
+ return
55
}
56
dagnodes = append(dagnodes, dagnode)
57
}
@@ -69,7 +71,7 @@ it contains, with the following format:
71
}
72
}
73
72
- return &LsOutput{output}, nil
74
+ res.SetOutput(&LsOutput{output})
75
},
76
Marshalers: cmds.MarshalerMap{
77
cmds.Text: func(res cmds.Response) (io.Reader, error) {
core/commands/mount_unix.go
+14
-8
@@ -90,25 +90,29 @@ baz
90
// TODO longform
91
cmds.StringOption("n", "The path where IPNS should be mounted"),
92
},
93
- Run: func(req cmds.Request) (interface{}, error) {
93
+ Run: func(req cmds.Request, res cmds.Response) {
94
cfg, err := req.Context().GetConfig()
95
if err != nil {
96
- return nil, err
96
+ res.SetError(err, cmds.ErrNormal)
97
+ return
98
}
99
100
node, err := req.Context().GetNode()
101
if err != nil {
101
- return nil, err
102
+ res.SetError(err, cmds.ErrNormal)
103
+ return
104
}
105
106
// error if we aren't running node in online mode
107
if !node.OnlineMode() {
106
- return nil, errNotOnline
108
+ res.SetError(errNotOnline, cmds.ErrClient)
109
+ return
110
}
111
112
fsdir, found, err := req.Option("f").String()
113
if err != nil {
111
- return nil, err
114
+ res.SetError(err, cmds.ErrNormal)
115
+ return
116
}
117
if !found {
118
fsdir = cfg.Mounts.IPFS // use default value
@@ -117,7 +121,8 @@ baz
121
// get default mount points
122
nsdir, found, err := req.Option("n").String()
123
if err != nil {
120
- return nil, err
124
+ res.SetError(err, cmds.ErrNormal)
125
+ return
126
}
127
if !found {
128
nsdir = cfg.Mounts.IPNS // NB: be sure to not redeclare!
@@ -125,13 +130,14 @@ baz
130
131
err = Mount(node, fsdir, nsdir)
132
if err != nil {
128
- return nil, err
133
+ res.SetError(err, cmds.ErrNormal)
134
+ return
135
}
136
137
var output config.Mounts
138
output.IPFS = fsdir
139
output.IPNS = nsdir
134
- return &output, nil
140
+ res.SetOutput(&output)
141
},
142
Type: config.Mounts{},
143
Marshalers: cmds.MarshalerMap{
core/commands/mount_windows.go
+2
-2
@@ -13,8 +13,8 @@ var MountCmd = &cmds.Command{
13
ShortDescription: "Not yet implemented on Windows. :(",
14
},
15
16
- Run: func(req cmds.Request) (interface{}, error) {
17
- return errors.New("Mount isn't compatible with Windows yet"), nil
16
+ Run: func(req cmds.Request, res cmds.Response) {
17
+ res.SetError(errors.New("Mount isn't compatible with Windows yet"), cmds.ErrNormal)
18
},
19
}
20
core/commands/object.go
+40
-20
@@ -71,14 +71,20 @@ output is the raw data of the object.
71
Arguments: []cmds.Argument{
72
cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format").EnableStdin(),
73
},
74
- Run: func(req cmds.Request) (interface{}, error) {
74
+ Run: func(req cmds.Request, res cmds.Response) {
75
n, err := req.Context().GetNode()
76
if err != nil {
77
- return nil, err
77
+ res.SetError(err, cmds.ErrNormal)
78
+ return
79
}
80
81
key := req.Arguments()[0]
81
- return objectData(n, key)
82
+ output, err := objectData(n, key)
83
+ if err != nil {
84
+ res.SetError(err, cmds.ErrNormal)
85
+ return
86
+ }
87
+ res.SetOutput(output)
88
},
89
}
90
@@ -95,14 +101,20 @@ multihash.
101
Arguments: []cmds.Argument{
102
cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format").EnableStdin(),
103
},
98
- Run: func(req cmds.Request) (interface{}, error) {
104
+ Run: func(req cmds.Request, res cmds.Response) {
105
n, err := req.Context().GetNode()
106
if err != nil {
101
- return nil, err
107
+ res.SetError(err, cmds.ErrNormal)
108
+ return
109
}
110
111
key := req.Arguments()[0]
105
- return objectLinks(n, key)
112
+ output, err := objectLinks(n, key)
113
+ if err != nil {
114
+ res.SetError(err, cmds.ErrNormal)
115
+ return
116
+ }
117
+ res.SetOutput(output)
118
},
119
Marshalers: cmds.MarshalerMap{
120
cmds.Text: func(res cmds.Response) (io.Reader, error) {
@@ -137,17 +149,19 @@ This command outputs data in the following encodings:
149
Arguments: []cmds.Argument{
150
cmds.StringArg("key", true, false, "Key of the object to retrieve (in base58-encoded multihash format)").EnableStdin(),
151
},
140
- Run: func(req cmds.Request) (interface{}, error) {
152
+ Run: func(req cmds.Request, res cmds.Response) {
153
n, err := req.Context().GetNode()
154
if err != nil {
143
- return nil, err
155
+ res.SetError(err, cmds.ErrNormal)
156
+ return
157
}
158
159
key := req.Arguments()[0]
160
161
object, err := objectGet(n, key)
162
if err != nil {
150
- return nil, err
163
+ res.SetError(err, cmds.ErrNormal)
164
+ return
165
}
166
167
node := &Node{
@@ -163,7 +177,7 @@ This command outputs data in the following encodings:
177
}
178
}
179
166
- return node, nil
180
+ res.SetOutput(node)
181
},
182
Type: Node{},
183
Marshalers: cmds.MarshalerMap{
@@ -201,25 +215,28 @@ var objectStatCmd = &cmds.Command{
215
Arguments: []cmds.Argument{
216
cmds.StringArg("key", true, false, "Key of the object to retrieve (in base58-encoded multihash format)").EnableStdin(),
217
},
204
- Run: func(req cmds.Request) (interface{}, error) {
218
+ Run: func(req cmds.Request, res cmds.Response) {
219
n, err := req.Context().GetNode()
220
if err != nil {
207
- return nil, err
221
+ res.SetError(err, cmds.ErrNormal)
222
+ return
223
}
224
225
key := req.Arguments()[0]
226
227
object, err := objectGet(n, key)
228
if err != nil {
214
- return nil, err
229
+ res.SetError(err, cmds.ErrNormal)
230
+ return
231
}
232
233
ns, err := object.Stat()
234
if err != nil {
219
- return nil, err
235
+ res.SetError(err, cmds.ErrNormal)
236
+ return
237
}
238
222
- return ns, nil
239
+ res.SetOutput(ns)
240
},
241
Type: dag.NodeStat{},
242
Marshalers: cmds.MarshalerMap{
@@ -263,15 +280,17 @@ Data should be in the format specified by <encoding>.
280
cmds.FileArg("data", true, false, "Data to be stored as a DAG object"),
281
cmds.StringArg("encoding", true, false, "Encoding type of <data>, either \"protobuf\" or \"json\""),
282
},
266
- Run: func(req cmds.Request) (interface{}, error) {
283
+ Run: func(req cmds.Request, res cmds.Response) {
284
n, err := req.Context().GetNode()
285
if err != nil {
269
- return nil, err
286
+ res.SetError(err, cmds.ErrNormal)
287
+ return
288
}
289
290
input, err := req.Files().NextFile()
291
if err != nil && err != io.EOF {
274
- return nil, err
292
+ res.SetError(err, cmds.ErrNormal)
293
+ return
294
}
295
296
encoding := req.Arguments()[0]
@@ -282,10 +301,11 @@ Data should be in the format specified by <encoding>.
301
if err == ErrUnknownObjectEnc {
302
errType = cmds.ErrClient
303
}
285
- return nil, cmds.Error{err.Error(), errType}
304
+ res.SetError(err, errType)
305
+ return
306
}
307
288
- return output, nil
308
+ res.SetOutput(output)
309
},
310
Marshalers: cmds.MarshalerMap{
311
cmds.Text: func(res cmds.Response) (io.Reader, error) {
core/commands/pin.go
+24
-15
@@ -42,16 +42,18 @@ on disk.
42
cmds.BoolOption("recursive", "r", "Recursively pin the object linked to by the specified object(s)"),
43
},
44
Type: PinOutput{},
45
- Run: func(req cmds.Request) (interface{}, error) {
45
+ Run: func(req cmds.Request, res cmds.Response) {
46
n, err := req.Context().GetNode()
47
if err != nil {
48
- return nil, err
48
+ res.SetError(err, cmds.ErrNormal)
49
+ return
50
}
51
52
// set recursive flag
53
recursive, found, err := req.Option("recursive").Bool()
54
if err != nil {
54
- return nil, err
55
+ res.SetError(err, cmds.ErrNormal)
56
+ return
57
}
58
if !found {
59
recursive = false
@@ -59,10 +61,11 @@ on disk.
61
62
added, err := corerepo.Pin(n, req.Arguments(), recursive)
63
if err != nil {
62
- return nil, err
64
+ res.SetError(err, cmds.ErrNormal)
65
+ return
66
}
67
65
- return &PinOutput{added}, nil
68
+ res.SetOutput(&PinOutput{added})
69
},
70
Marshalers: cmds.MarshalerMap{
71
cmds.Text: func(res cmds.Response) (io.Reader, error) {
@@ -104,16 +107,18 @@ collected if needed.
107
cmds.BoolOption("recursive", "r", "Recursively unpin the object linked to by the specified object(s)"),
108
},
109
Type: PinOutput{},
107
- Run: func(req cmds.Request) (interface{}, error) {
110
+ Run: func(req cmds.Request, res cmds.Response) {
111
n, err := req.Context().GetNode()
112
if err != nil {
110
- return nil, err
113
+ res.SetError(err, cmds.ErrNormal)
114
+ return
115
}
116
117
// set recursive flag
118
recursive, found, err := req.Option("recursive").Bool()
119
if err != nil {
116
- return nil, err
120
+ res.SetError(err, cmds.ErrNormal)
121
+ return
122
}
123
if !found {
124
recursive = false // default
@@ -121,10 +126,11 @@ collected if needed.
126
127
removed, err := corerepo.Unpin(n, req.Arguments(), recursive)
128
if err != nil {
124
- return nil, err
129
+ res.SetError(err, cmds.ErrNormal)
130
+ return
131
}
132
127
- return &PinOutput{removed}, nil
133
+ res.SetOutput(&PinOutput{removed})
134
},
135
Marshalers: cmds.MarshalerMap{
136
cmds.Text: func(res cmds.Response) (io.Reader, error) {
@@ -165,15 +171,17 @@ Use --type=<type> to specify the type of pinned keys to list. Valid values are:
171
Options: []cmds.Option{
172
cmds.StringOption("type", "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\". Defaults to \"direct\""),
173
},
168
- Run: func(req cmds.Request) (interface{}, error) {
174
+ Run: func(req cmds.Request, res cmds.Response) {
175
n, err := req.Context().GetNode()
176
if err != nil {
171
- return nil, err
177
+ res.SetError(err, cmds.ErrNormal)
178
+ return
179
}
180
181
typeStr, found, err := req.Option("type").String()
182
if err != nil {
176
- return nil, err
183
+ res.SetError(err, cmds.ErrNormal)
184
+ return
185
}
186
if !found {
187
typeStr = "direct"
@@ -182,7 +190,8 @@ Use --type=<type> to specify the type of pinned keys to list. Valid values are:
190
switch typeStr {
191
case "all", "direct", "indirect", "recursive":
192
default:
185
- return nil, cmds.ClientError("Invalid type '" + typeStr + "', must be one of {direct, indirect, recursive, all}")
193
+ err = fmt.Errorf("Invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr)
194
+ res.SetError(err, cmds.ErrClient)
195
}
196
197
keys := make([]u.Key, 0)
@@ -196,7 +205,7 @@ Use --type=<type> to specify the type of pinned keys to list. Valid values are:
205
keys = append(keys, n.Pinning.RecursiveKeys()...)
206
}
207
199
- return &KeyList{Keys: keys}, nil
208
+ res.SetOutput(&KeyList{Keys: keys})
209
},
210
Type: KeyList{},
211
Marshalers: cmds.MarshalerMap{
core/commands/ping.go
+10
-6
@@ -74,21 +74,24 @@ trip latency information.
74
}, nil
75
},
76
},
77
- Run: func(req cmds.Request) (interface{}, error) {
77
+ Run: func(req cmds.Request, res cmds.Response) {
78
ctx := req.Context().Context
79
n, err := req.Context().GetNode()
80
if err != nil {
81
- return nil, err
81
+ res.SetError(err, cmds.ErrNormal)
82
+ return
83
}
84
85
// Must be online!
86
if !n.OnlineMode() {
86
- return nil, errNotOnline
87
+ res.SetError(errNotOnline, cmds.ErrClient)
88
+ return
89
}
90
91
addr, peerID, err := ParsePeerParam(req.Arguments()[0])
92
if err != nil {
91
- return nil, err
93
+ res.SetError(err, cmds.ErrNormal)
94
+ return
95
}
96
97
if addr != nil {
@@ -99,14 +102,15 @@ trip latency information.
102
numPings := 10
103
val, found, err := req.Option("count").Int()
104
if err != nil {
102
- return nil, err
105
+ res.SetError(err, cmds.ErrNormal)
106
+ return
107
}
108
if found {
109
numPings = val
110
}
111
112
outChan := pingPeer(ctx, n, peerID, numPings)
109
- return outChan, nil
113
+ res.SetOutput(outChan)
114
},
115
Type: PingResult{},
116
}
core/commands/publish.go
+13
-6
@@ -46,21 +46,23 @@ Publish a <ref> to another public key:
46
cmds.StringArg("name", false, false, "The IPNS name to publish to. Defaults to your node's peerID"),
47
cmds.StringArg("ipfs-path", true, false, "IPFS path of the obejct to be published at <name>").EnableStdin(),
48
},
49
- Run: func(req cmds.Request) (interface{}, error) {
49
+ Run: func(req cmds.Request, res cmds.Response) {
50
log.Debug("Begin Publish")
51
n, err := req.Context().GetNode()
52
if err != nil {
53
- return nil, err
53
+ res.SetError(err, cmds.ErrNormal)
54
+ return
55
}
56
57
args := req.Arguments()
58
59
if n.PeerHost == nil {
59
- return nil, errNotOnline
60
+ res.SetError(errNotOnline, cmds.ErrClient)
61
}
62
63
if n.Identity == "" {
63
- return nil, errors.New("Identity not loaded!")
64
+ res.SetError(errors.New("Identity not loaded!"), cmds.ErrNormal)
65
+ return
66
}
67
68
// name := ""
@@ -70,14 +72,19 @@ Publish a <ref> to another public key:
72
case 2:
73
// name = args[0]
74
ref = args[1]
73
- return nil, errors.New("keychains not yet implemented")
75
+ res.SetError(errors.New("keychains not yet implemented"), cmds.ErrNormal)
76
case 1:
77
// name = n.Identity.ID.String()
78
ref = args[0]
79
}
80
81
// TODO n.Keychain.Get(name).PrivKey
80
- return publish(n, n.PrivateKey, ref)
82
+ output, err := publish(n, n.PrivateKey, ref)
83
+ if err != nil {
84
+ res.SetError(err, cmds.ErrNormal)
85
+ return
86
+ }
87
+ res.SetOutput(output)
88
},
89
Marshalers: cmds.MarshalerMap{
90
cmds.Text: func(res cmds.Response) (io.Reader, error) {
core/commands/refs.go
+20
-12
@@ -53,36 +53,42 @@ Note: list all refs recursively with -r.
53
cmds.BoolOption("unique", "u", "Omit duplicate refs from output"),
54
cmds.BoolOption("recursive", "r", "Recursively list links of child nodes"),
55
},
56
- Run: func(req cmds.Request) (interface{}, error) {
56
+ Run: func(req cmds.Request, res cmds.Response) {
57
ctx := req.Context().Context
58
n, err := req.Context().GetNode()
59
if err != nil {
60
- return nil, err
60
+ res.SetError(err, cmds.ErrNormal)
61
+ return
62
}
63
64
unique, _, err := req.Option("unique").Bool()
65
if err != nil {
65
- return nil, err
66
+ res.SetError(err, cmds.ErrNormal)
67
+ return
68
}
69
70
recursive, _, err := req.Option("recursive").Bool()
71
if err != nil {
70
- return nil, err
72
+ res.SetError(err, cmds.ErrNormal)
73
+ return
74
}
75
76
edges, _, err := req.Option("edges").Bool()
77
if err != nil {
75
- return nil, err
78
+ res.SetError(err, cmds.ErrNormal)
79
+ return
80
}
81
82
format, _, err := req.Option("format").String()
83
if err != nil {
80
- return nil, err
84
+ res.SetError(err, cmds.ErrNormal)
85
+ return
86
}
87
88
objs, err := objectsForPaths(n, req.Arguments())
89
if err != nil {
85
- return nil, err
90
+ res.SetError(err, cmds.ErrNormal)
91
+ return
92
}
93
94
piper, pipew := io.Pipe()
@@ -110,7 +116,7 @@ Note: list all refs recursively with -r.
116
}
117
}()
118
113
- return eptr, nil
119
+ res.SetOutput(eptr)
120
},
121
}
122
@@ -122,17 +128,19 @@ Displays the hashes of all local objects.
128
`,
129
},
130
125
- Run: func(req cmds.Request) (interface{}, error) {
131
+ Run: func(req cmds.Request, res cmds.Response) {
132
ctx := req.Context().Context
133
n, err := req.Context().GetNode()
134
if err != nil {
129
- return nil, err
135
+ res.SetError(err, cmds.ErrNormal)
136
+ return
137
}
138
139
// todo: make async
140
allKeys, err := n.Blockstore.AllKeysChan(ctx, 0, 0)
141
if err != nil {
135
- return nil, err
142
+ res.SetError(err, cmds.ErrNormal)
143
+ return
144
}
145
146
piper, pipew := io.Pipe()
@@ -151,7 +159,7 @@ Displays the hashes of all local objects.
159
}
160
}()
161
154
- return eptr, nil
162
+ res.SetOutput(eptr)
163
},
164
}
165
core/commands/repo.go
+7
-5
@@ -36,26 +36,28 @@ order to reclaim hard disk space.
36
Options: []cmds.Option{
37
cmds.BoolOption("quiet", "q", "Write minimal output"),
38
},
39
- Run: func(req cmds.Request) (interface{}, error) {
39
+ Run: func(req cmds.Request, res cmds.Response) {
40
n, err := req.Context().GetNode()
41
if err != nil {
42
- return nil, err
42
+ res.SetError(err, cmds.ErrNormal)
43
+ return
44
}
45
46
gcOutChan, err := corerepo.GarbageCollectBlockstore(n, req.Context().Context)
47
if err != nil {
47
- return nil, err
48
+ res.SetError(err, cmds.ErrNormal)
49
+ return
50
}
51
52
outChan := make(chan interface{})
53
+ res.SetOutput((<-chan interface{})(outChan))
54
+
55
go func() {
56
defer close(outChan)
57
for k := range gcOutChan {
58
outChan <- k
59
}
60
}()
57
-
58
- return outChan, nil
61
},
62
Type: corerepo.KeyRemoved{},
63
Marshalers: cmds.MarshalerMap{
core/commands/resolve.go
+10
-6
@@ -40,22 +40,25 @@ Resolve te value of another name:
40
Arguments: []cmds.Argument{
41
cmds.StringArg("name", false, false, "The IPNS name to resolve. Defaults to your node's peerID.").EnableStdin(),
42
},
43
- Run: func(req cmds.Request) (interface{}, error) {
43
+ Run: func(req cmds.Request, res cmds.Response) {
44
45
n, err := req.Context().GetNode()
46
if err != nil {
47
- return nil, err
47
+ res.SetError(err, cmds.ErrNormal)
48
+ return
49
}
50
51
var name string
52
53
if n.PeerHost == nil {
53
- return nil, errNotOnline
54
+ res.SetError(errNotOnline, cmds.ErrClient)
55
+ return
56
}
57
58
if len(req.Arguments()) == 0 {
59
if n.Identity == "" {
58
- return nil, errors.New("Identity not loaded!")
60
+ res.SetError(errors.New("Identity not loaded!"), cmds.ErrNormal)
61
+ return
62
}
63
name = n.Identity.Pretty()
64
@@ -65,12 +68,13 @@ Resolve te value of another name:
68
69
output, err := n.Namesys.Resolve(name)
70
if err != nil {
68
- return nil, err
71
+ res.SetError(err, cmds.ErrNormal)
72
+ return
73
}
74
75
// TODO: better errors (in the case of not finding the name, we get "failed to find any peer in table")
76
73
- return output, nil
77
+ res.SetOutput(output)
78
},
79
Marshalers: cmds.MarshalerMap{
80
cmds.Text: func(res cmds.Response) (io.Reader, error) {
core/commands/swarm.go
+14
-9
@@ -45,16 +45,18 @@ var swarmPeersCmd = &cmds.Command{
45
ipfs swarm peers lists the set of peers this node is connected to.
46
`,
47
},
48
- Run: func(req cmds.Request) (interface{}, error) {
48
+ Run: func(req cmds.Request, res cmds.Response) {
49
50
log.Debug("ipfs swarm peers")
51
n, err := req.Context().GetNode()
52
if err != nil {
53
- return nil, err
53
+ res.SetError(err, cmds.ErrNormal)
54
+ return
55
}
56
57
if n.PeerHost == nil {
57
- return nil, errNotOnline
58
+ res.SetError(errNotOnline, cmds.ErrClient)
59
+ return
60
}
61
62
conns := n.PeerHost.Network().Conns()
@@ -66,7 +68,7 @@ ipfs swarm peers lists the set of peers this node is connected to.
68
}
69
70
sort.Sort(sort.StringSlice(addrs))
69
- return &stringList{addrs}, nil
71
+ res.SetOutput(&stringList{addrs})
72
},
73
Marshalers: cmds.MarshalerMap{
74
cmds.Text: stringListMarshaler,
@@ -87,24 +89,27 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/QmaCpDMGvV2BGHeYERUEnRQAwe3N8Szb
89
Arguments: []cmds.Argument{
90
cmds.StringArg("address", true, true, "address of peer to connect to").EnableStdin(),
91
},
90
- Run: func(req cmds.Request) (interface{}, error) {
92
+ Run: func(req cmds.Request, res cmds.Response) {
93
ctx := context.TODO()
94
95
log.Debug("ipfs swarm connect")
96
n, err := req.Context().GetNode()
97
if err != nil {
96
- return nil, err
98
+ res.SetError(err, cmds.ErrNormal)
99
+ return
100
}
101
102
addrs := req.Arguments()
103
104
if n.PeerHost == nil {
102
- return nil, errNotOnline
105
+ res.SetError(errNotOnline, cmds.ErrClient)
106
+ return
107
}
108
109
peers, err := peersWithAddresses(n.Peerstore, addrs)
110
if err != nil {
107
- return nil, err
111
+ res.SetError(err, cmds.ErrNormal)
112
+ return
113
}
114
115
output := make([]string, len(peers))
@@ -119,7 +124,7 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/QmaCpDMGvV2BGHeYERUEnRQAwe3N8Szb
124
}
125
}
126
122
- return &stringList{output}, nil
127
+ res.SetOutput(&stringList{output})
128
},
129
Marshalers: cmds.MarshalerMap{
130
cmds.Text: stringListMarshaler,
core/commands/update.go
+30
-9
@@ -22,12 +22,19 @@ var UpdateCmd = &cmds.Command{
22
ShortDescription: "ipfs update is a utility command used to check for updates and apply them.",
23
},
24
25
- Run: func(req cmds.Request) (interface{}, error) {
25
+ Run: func(req cmds.Request, res cmds.Response) {
26
n, err := req.Context().GetNode()
27
if err != nil {
28
- return nil, err
28
+ res.SetError(err, cmds.ErrNormal)
29
+ return
30
}
30
- return updateApply(n)
31
+
32
+ output, err := updateApply(n)
33
+ if err != nil {
34
+ res.SetError(err, cmds.ErrNormal)
35
+ return
36
+ }
37
+ res.SetOutput(output)
38
},
39
Type: UpdateOutput{},
40
Subcommands: map[string]*cmds.Command{
@@ -55,12 +62,19 @@ var UpdateCheckCmd = &cmds.Command{
62
ShortDescription: "'ipfs update check' checks if any updates are available for IPFS.\nNothing will be downloaded or installed.",
63
},
64
58
- Run: func(req cmds.Request) (interface{}, error) {
65
+ Run: func(req cmds.Request, res cmds.Response) {
66
n, err := req.Context().GetNode()
67
if err != nil {
61
- return nil, err
68
+ res.SetError(err, cmds.ErrNormal)
69
+ return
70
}
63
- return updateCheck(n)
71
+
72
+ output, err := updateCheck(n)
73
+ if err != nil {
74
+ res.SetError(err, cmds.ErrNormal)
75
+ return
76
+ }
77
+ res.SetOutput(output)
78
},
79
Type: UpdateOutput{},
80
Marshalers: cmds.MarshalerMap{
@@ -84,12 +98,19 @@ var UpdateLogCmd = &cmds.Command{
98
ShortDescription: "This command is not yet implemented.",
99
},
100
87
- Run: func(req cmds.Request) (interface{}, error) {
101
+ Run: func(req cmds.Request, res cmds.Response) {
102
n, err := req.Context().GetNode()
103
if err != nil {
90
- return nil, err
104
+ res.SetError(err, cmds.ErrNormal)
105
+ return
106
+ }
107
+
108
+ output, err := updateLog(n)
109
+ if err != nil {
110
+ res.SetError(err, cmds.ErrNormal)
111
+ return
112
}
92
- return updateLog(n)
113
+ res.SetOutput(output)
114
},
115
}
116
core/commands/version.go
+3
-3
@@ -22,10 +22,10 @@ var VersionCmd = &cmds.Command{
22
Options: []cmds.Option{
23
cmds.BoolOption("number", "n", "Only show the version number"),
24
},
25
- Run: func(req cmds.Request) (interface{}, error) {
26
- return &VersionOutput{
25
+ Run: func(req cmds.Request, res cmds.Response) {
26
+ res.SetOutput(&VersionOutput{
27
Version: config.CurrentVersionNumber,
28
- }, nil
28
+ })
29
},
30
Marshalers: cmds.MarshalerMap{
31
cmds.Text: func(res cmds.Response) (io.Reader, error) {