@cryptotaxi247 / kubo / commits / 7b4de230e

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) {