delete dead code
This code was making it *really* hard to understand the commands code. License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
Steven Allen committed
Mar 16, 2018 at 11:00 UTC
c24a08be2ebb91d1c472442561b5369583c1177f
7 files changed
-1068
commands/channelmarshaler.go
deleted
-44
@@ -1,44 +0,0 @@
1
-package commands
2
-
3
-import (
4
- "io"
5
-)
6
-
7
-type ChannelMarshaler struct {
8
- Channel <-chan interface{}
9
- Marshaler func(interface{}) (io.Reader, error)
10
- Res Response
11
-
12
- reader io.Reader
13
-}
14
-
15
-func (cr *ChannelMarshaler) Read(p []byte) (int, error) {
16
- if cr.reader == nil {
17
- val, more := <-cr.Channel
18
- if !more {
19
- //check error in response
20
- if cr.Res.Error() != nil {
21
- return 0, cr.Res.Error()
22
- }
23
- return 0, io.EOF
24
- }
25
-
26
- r, err := cr.Marshaler(val)
27
- if err != nil {
28
- return 0, err
29
- }
30
- if r == nil {
31
- return 0, nil
32
- }
33
- cr.reader = r
34
- }
35
-
36
- n, err := cr.reader.Read(p)
37
- if err != nil && err != io.EOF {
38
- return n, err
39
- }
40
- if n == 0 {
41
- cr.reader = nil
42
- }
43
- return n, nil
44
-}
commands/command.go
-228
@@ -9,15 +9,9 @@ output to the user, including text, JSON, and XML marshallers.
9
package commands
10
11
import (
12
- "errors"
13
- "fmt"
12
"io"
15
- "reflect"
16
-
17
- "github.com/ipfs/go-ipfs/path"
13
14
logging "gx/ipfs/QmRb5jh8z2E8hMGN2tkvs1yHynUanqnZ3UeKwgN1i9P1F8/go-log"
20
- cmds "gx/ipfs/QmabLouZTZwhfALuBcssPvkzhbYGMb4394huT7HY4LQ6d3/go-ipfs-cmds"
15
cmdkit "gx/ipfs/QmceUdzxkimdYsgtX733uNgzf1DLHyBKN6ehGSp85ayppM/go-ipfs-cmdkit"
16
)
17
@@ -64,233 +58,11 @@ type Command struct {
58
Subcommands map[string]*Command
59
}
60
67
-// ErrNotCallable signals a command that cannot be called.
68
-var ErrNotCallable = ClientError("This command can't be called directly. Try one of its subcommands.")
69
-
70
-var ErrNoFormatter = ClientError("This command cannot be formatted to plain text")
71
-
72
-var ErrIncorrectType = errors.New("The command returned a value with a different type than expected")
73
-
74
-// Call invokes the command for the given Request
75
-func (c *Command) Call(req Request) Response {
76
- res := NewResponse(req)
77
-
78
- cmds, err := c.Resolve(req.Path())
79
- if err != nil {
80
- res.SetError(err, cmdkit.ErrClient)
81
- return res
82
- }
83
- cmd := cmds[len(cmds)-1]
84
-
85
- if cmd.Run == nil {
86
- res.SetError(ErrNotCallable, cmdkit.ErrClient)
87
- return res
88
- }
89
-
90
- err = cmd.CheckArguments(req)
91
- if err != nil {
92
- res.SetError(err, cmdkit.ErrClient)
93
- return res
94
- }
95
-
96
- err = req.ConvertOptions()
97
- if err != nil {
98
- res.SetError(err, cmdkit.ErrClient)
99
- return res
100
- }
101
-
102
- cmd.Run(req, res)
103
- if res.Error() != nil {
104
- return res
105
- }
106
-
107
- output := res.Output()
108
- isChan := false
109
- actualType := reflect.TypeOf(output)
110
- if actualType != nil {
111
- if actualType.Kind() == reflect.Ptr {
112
- actualType = actualType.Elem()
113
- }
114
-
115
- // test if output is a channel
116
- isChan = actualType.Kind() == reflect.Chan
117
- }
118
-
119
- // If the command specified an output type, ensure the actual value
120
- // returned is of that type
121
- if cmd.Type != nil && !isChan {
122
- expectedType := reflect.TypeOf(cmd.Type)
123
-
124
- if actualType != expectedType {
125
- res.SetError(ErrIncorrectType, cmdkit.ErrNormal)
126
- return res
127
- }
128
- }
129
-
130
- return res
131
-}
132
-
133
-// Resolve returns the subcommands at the given path
134
-func (c *Command) Resolve(pth []string) ([]*Command, error) {
135
- cmds := make([]*Command, len(pth)+1)
136
- cmds[0] = c
137
-
138
- cmd := c
139
- for i, name := range pth {
140
- cmd = cmd.Subcommand(name)
141
-
142
- if cmd == nil {
143
- pathS := path.Join(pth[:i])
144
- return nil, fmt.Errorf("Undefined command: '%s'", pathS)
145
- }
146
-
147
- cmds[i+1] = cmd
148
- }
149
-
150
- return cmds, nil
151
-}
152
-
153
-// Get resolves and returns the Command addressed by path
154
-func (c *Command) Get(path []string) (*Command, error) {
155
- cmds, err := c.Resolve(path)
156
- if err != nil {
157
- return nil, err
158
- }
159
- return cmds[len(cmds)-1], nil
160
-}
161
-
162
-// GetOptions returns the options in the given path of commands
163
-func (c *Command) GetOptions(path []string) (map[string]cmdkit.Option, error) {
164
- options := make([]cmdkit.Option, 0, len(c.Options))
165
-
166
- cmds, err := c.Resolve(path)
167
- if err != nil {
168
- return nil, err
169
- }
170
- cmds = append(cmds, globalCommand)
171
-
172
- for _, cmd := range cmds {
173
- options = append(options, cmd.Options...)
174
- }
175
-
176
- optionsMap := make(map[string]cmdkit.Option)
177
- for _, opt := range options {
178
- for _, name := range opt.Names() {
179
- if _, found := optionsMap[name]; found {
180
- return nil, fmt.Errorf("Option name '%s' used multiple times", name)
181
- }
182
-
183
- optionsMap[name] = opt
184
- }
185
- }
186
-
187
- return optionsMap, nil
188
-}
189
-
190
-func (c *Command) CheckArguments(req Request) error {
191
- args := req.(*request).arguments
192
-
193
- // count required argument definitions
194
- numRequired := 0
195
- for _, argDef := range c.Arguments {
196
- if argDef.Required {
197
- numRequired++
198
- }
199
- }
200
-
201
- // iterate over the arg definitions
202
- valueIndex := 0 // the index of the current value (in `args`)
203
- for i, argDef := range c.Arguments {
204
- // skip optional argument definitions if there aren't
205
- // sufficient remaining values
206
- if len(args)-valueIndex <= numRequired && !argDef.Required ||
207
- argDef.Type == cmdkit.ArgFile {
208
- continue
209
- }
210
-
211
- // the value for this argument definition. can be nil if it
212
- // wasn't provided by the caller
213
- v, found := "", false
214
- if valueIndex < len(args) {
215
- v = args[valueIndex]
216
- found = true
217
- valueIndex++
218
- }
219
-
220
- // in the case of a non-variadic required argument that supports stdin
221
- if !found && len(c.Arguments)-1 == i && argDef.SupportsStdin {
222
- found = true
223
- }
224
-
225
- err := checkArgValue(v, found, argDef)
226
- if err != nil {
227
- return err
228
- }
229
-
230
- // any additional values are for the variadic arg definition
231
- if argDef.Variadic && valueIndex < len(args)-1 {
232
- for _, val := range args[valueIndex:] {
233
- err := checkArgValue(val, true, argDef)
234
- if err != nil {
235
- return err
236
- }
237
- }
238
- }
239
- }
240
-
241
- return nil
242
-}
243
-
61
// Subcommand returns the subcommand with the given id
62
func (c *Command) Subcommand(id string) *Command {
63
return c.Subcommands[id]
64
}
65
249
-type CommandVisitor func(*Command)
250
-
251
-// Walks tree of all subcommands (including this one)
252
-func (c *Command) Walk(visitor CommandVisitor) {
253
- visitor(c)
254
- for _, cm := range c.Subcommands {
255
- cm.Walk(visitor)
256
- }
257
-}
258
-
259
-func (c *Command) ProcessHelp() {
260
- c.Walk(func(cm *Command) {
261
- ht := &cm.Helptext
262
- if len(ht.LongDescription) == 0 {
263
- ht.LongDescription = ht.ShortDescription
264
- }
265
- })
266
-}
267
-
268
-// checkArgValue returns an error if a given arg value is not valid for the
269
-// given Argument
270
-func checkArgValue(v string, found bool, def cmdkit.Argument) error {
271
- if def.Variadic && def.SupportsStdin {
272
- return nil
273
- }
274
-
275
- if !found && def.Required {
276
- return fmt.Errorf("Argument '%s' is required", def.Name)
277
- }
278
-
279
- return nil
280
-}
281
-
66
func ClientError(msg string) error {
67
return &cmdkit.Error{Code: cmdkit.ErrClient, Message: msg}
68
}
285
-
286
-// global options, added to every command
287
-var globalOptions = []cmdkit.Option{
288
- cmds.OptionEncodingType,
289
- cmds.OptionStreamChannels,
290
- cmds.OptionTimeout,
291
-}
292
-
293
-// the above array of Options, wrapped in a Command
294
-var globalCommand = &Command{
295
- Options: globalOptions,
296
-}
commands/command_test.go
deleted
-200
@@ -1,200 +0,0 @@
1
-package commands
2
-
3
-import (
4
- "testing"
5
-
6
- cmds "gx/ipfs/QmabLouZTZwhfALuBcssPvkzhbYGMb4394huT7HY4LQ6d3/go-ipfs-cmds"
7
- cmdkit "gx/ipfs/QmceUdzxkimdYsgtX733uNgzf1DLHyBKN6ehGSp85ayppM/go-ipfs-cmdkit"
8
-)
9
-
10
-func noop(req Request, res Response) {
11
-}
12
-
13
-func TestOptionValidation(t *testing.T) {
14
- cmd := Command{
15
- Options: []cmdkit.Option{
16
- cmdkit.IntOption("b", "beep", "enables beeper"),
17
- cmdkit.StringOption("B", "boop", "password for booper"),
18
- },
19
- Run: noop,
20
- }
21
-
22
- opts, _ := cmd.GetOptions(nil)
23
-
24
- req, _ := NewRequest(nil, nil, nil, nil, nil, opts)
25
- req.SetOption("beep", true)
26
- res := cmd.Call(req)
27
- if res.Error() == nil {
28
- t.Error("Should have failed (incorrect type)")
29
- }
30
-
31
- req, _ = NewRequest(nil, nil, nil, nil, nil, opts)
32
- req.SetOption("beep", 5)
33
- res = cmd.Call(req)
34
- if res.Error() != nil {
35
- t.Error(res.Error(), "Should have passed")
36
- }
37
-
38
- req, _ = NewRequest(nil, nil, nil, nil, nil, opts)
39
- req.SetOption("beep", 5)
40
- req.SetOption("boop", "test")
41
- res = cmd.Call(req)
42
- if res.Error() != nil {
43
- t.Error("Should have passed")
44
- }
45
-
46
- req, _ = NewRequest(nil, nil, nil, nil, nil, opts)
47
- req.SetOption("b", 5)
48
- req.SetOption("B", "test")
49
- res = cmd.Call(req)
50
- if res.Error() != nil {
51
- t.Error("Should have passed")
52
- }
53
-
54
- req, _ = NewRequest(nil, nil, nil, nil, nil, opts)
55
- req.SetOption("foo", 5)
56
- res = cmd.Call(req)
57
- if res.Error() != nil {
58
- t.Error("Should have passed")
59
- }
60
-
61
- req, _ = NewRequest(nil, nil, nil, nil, nil, opts)
62
- req.SetOption(cmds.EncLong, "json")
63
- res = cmd.Call(req)
64
- if res.Error() != nil {
65
- t.Error("Should have passed")
66
- }
67
-
68
- req, _ = NewRequest(nil, nil, nil, nil, nil, opts)
69
- req.SetOption("b", "100")
70
- res = cmd.Call(req)
71
- if res.Error() != nil {
72
- t.Error("Should have passed")
73
- }
74
-
75
- req, _ = NewRequest(nil, nil, nil, nil, &cmd, opts)
76
- req.SetOption("b", ":)")
77
- res = cmd.Call(req)
78
- if res.Error() == nil {
79
- t.Error("Should have failed (string value not convertible to int)")
80
- }
81
-
82
- err := req.SetOptions(map[string]interface{}{
83
- "b": 100,
84
- })
85
- if err != nil {
86
- t.Error("Should have passed")
87
- }
88
-
89
- err = req.SetOptions(map[string]interface{}{
90
- "b": ":)",
91
- })
92
- if err == nil {
93
- t.Error("Should have failed (string value not convertible to int)")
94
- }
95
-}
96
-
97
-func TestRegistration(t *testing.T) {
98
- cmdA := &Command{
99
- Options: []cmdkit.Option{
100
- cmdkit.IntOption("beep", "number of beeps"),
101
- },
102
- Run: noop,
103
- }
104
-
105
- cmdB := &Command{
106
- Options: []cmdkit.Option{
107
- cmdkit.IntOption("beep", "number of beeps"),
108
- },
109
- Run: noop,
110
- Subcommands: map[string]*Command{
111
- "a": cmdA,
112
- },
113
- }
114
-
115
- cmdC := &Command{
116
- Options: []cmdkit.Option{
117
- cmdkit.StringOption("encoding", "data encoding type"),
118
- },
119
- Run: noop,
120
- }
121
-
122
- path := []string{"a"}
123
- _, err := cmdB.GetOptions(path)
124
- if err == nil {
125
- t.Error("Should have failed (option name collision)")
126
- }
127
-
128
- _, err = cmdC.GetOptions(nil)
129
- if err == nil {
130
- t.Error("Should have failed (option name collision with global options)")
131
- }
132
-}
133
-
134
-func TestResolving(t *testing.T) {
135
- cmdC := &Command{}
136
- cmdB := &Command{
137
- Subcommands: map[string]*Command{
138
- "c": cmdC,
139
- },
140
- }
141
- cmdB2 := &Command{}
142
- cmdA := &Command{
143
- Subcommands: map[string]*Command{
144
- "b": cmdB,
145
- "B": cmdB2,
146
- },
147
- }
148
- cmd := &Command{
149
- Subcommands: map[string]*Command{
150
- "a": cmdA,
151
- },
152
- }
153
-
154
- cmds, err := cmd.Resolve([]string{"a", "b", "c"})
155
- if err != nil {
156
- t.Error(err)
157
- }
158
- if len(cmds) != 4 || cmds[0] != cmd || cmds[1] != cmdA || cmds[2] != cmdB || cmds[3] != cmdC {
159
- t.Error("Returned command path is different than expected", cmds)
160
- }
161
-}
162
-
163
-func TestWalking(t *testing.T) {
164
- cmdA := &Command{
165
- Subcommands: map[string]*Command{
166
- "b": &Command{},
167
- "B": &Command{},
168
- },
169
- }
170
- i := 0
171
- cmdA.Walk(func(c *Command) {
172
- i = i + 1
173
- })
174
- if i != 3 {
175
- t.Error("Command tree walk didn't work, expected 3 got:", i)
176
- }
177
-}
178
-
179
-func TestHelpProcessing(t *testing.T) {
180
- cmdB := &Command{
181
- Helptext: cmdkit.HelpText{
182
- ShortDescription: "This is other short",
183
- },
184
- }
185
- cmdA := &Command{
186
- Helptext: cmdkit.HelpText{
187
- ShortDescription: "This is short",
188
- },
189
- Subcommands: map[string]*Command{
190
- "a": cmdB,
191
- },
192
- }
193
- cmdA.ProcessHelp()
194
- if len(cmdA.Helptext.LongDescription) == 0 {
195
- t.Error("LongDescription was not set on basis of ShortDescription")
196
- }
197
- if len(cmdB.Helptext.LongDescription) == 0 {
198
- t.Error("LongDescription was not set on basis of ShortDescription")
199
- }
200
-}
commands/legacy/request.go
-26
@@ -147,32 +147,6 @@ func (r *requestWrapper) Values() map[string]interface{} {
147
return nil
148
}
149
150
-func (r *requestWrapper) VarArgs(f func(string) error) error {
151
- if len(r.req.Arguments) >= len(r.req.Command.Arguments) {
152
- for _, arg := range r.req.Arguments {
153
- err := f(arg)
154
- if err != nil {
155
- return err
156
- }
157
- }
158
- return nil
159
- }
160
-
161
- s, err := r.req.BodyArgs()
162
- if err != nil {
163
- return err
164
- }
165
-
166
- for s.Scan() {
167
- err = f(s.Text())
168
- if err != nil {
169
- return err
170
- }
171
- }
172
-
173
- return nil
174
-}
175
-
150
// copied from go-ipfs-cmds/request.go
151
func convertOptions(req *cmds.Request) error {
152
optDefSlice := req.Command.Options
commands/request.go
-319
@@ -1,20 +1,13 @@
1
package commands
2
3
import (
4
- "bufio"
4
"context"
5
"errors"
7
- "fmt"
8
- "io"
9
- "os"
10
- "reflect"
11
- "strconv"
6
"strings"
7
"time"
8
9
"github.com/ipfs/go-ipfs/core"
10
"github.com/ipfs/go-ipfs/repo/config"
17
- u "gx/ipfs/QmNiJuT8Ja3hMVpBHXv3Q6dwmperaQ6JjLtpMQgMCD7xvx/go-ipfs-util"
11
12
"gx/ipfs/QmabLouZTZwhfALuBcssPvkzhbYGMb4394huT7HY4LQ6d3/go-ipfs-cmds"
13
"gx/ipfs/QmceUdzxkimdYsgtX733uNgzf1DLHyBKN6ehGSp85ayppM/go-ipfs-cmdkit"
@@ -59,12 +52,6 @@ func (c *Context) GetNode() (*core.IpfsNode, error) {
52
return c.node, err
53
}
54
62
-// NodeWithoutConstructing returns the underlying node variable
63
-// so that clients may close it.
64
-func (c *Context) NodeWithoutConstructing() *core.IpfsNode {
65
- return c.node
66
-}
67
-
55
// Context returns the node's context.
56
func (c *Context) Context() context.Context {
57
n, err := c.GetNode()
@@ -112,316 +99,10 @@ type Request interface {
99
Path() []string
100
Option(name string) *cmdkit.OptionValue
101
Options() cmdkit.OptMap
115
- SetOption(name string, val interface{})
116
- SetOptions(opts cmdkit.OptMap) error
102
Arguments() []string
103
StringArguments() []string
119
- SetArguments([]string)
104
Files() files.File
121
- SetFiles(files.File)
105
Context() context.Context
106
InvocContext() *Context
124
- SetInvocContext(Context)
107
Command() *Command
126
- Values() map[string]interface{}
127
- Stdin() io.Reader
128
- VarArgs(func(string) error) error
129
-
130
- ConvertOptions() error
131
-}
132
-
133
-type request struct {
134
- path []string
135
- options cmdkit.OptMap
136
- arguments []string
137
- files files.File
138
- cmd *Command
139
- ctx Context
140
- rctx context.Context
141
- optionDefs map[string]cmdkit.Option
142
- values map[string]interface{}
143
- stdin io.Reader
144
-}
145
-
146
-// Path returns the command path of this request
147
-func (r *request) Path() []string {
148
- return r.path
149
-}
150
-
151
-// Option returns the value of the option for given name.
152
-func (r *request) Option(name string) *cmdkit.OptionValue {
153
- // find the option with the specified name
154
- option, found := r.optionDefs[name]
155
- if !found {
156
- return nil
157
- }
158
-
159
- // try all the possible names, break if we find a value
160
- for _, n := range option.Names() {
161
- val, found := r.options[n]
162
- if found {
163
- return &cmdkit.OptionValue{
164
- Value: val,
165
- ValueFound: found,
166
- Def: option,
167
- }
168
- }
169
- }
170
-
171
- return &cmdkit.OptionValue{
172
- Value: option.Default(),
173
- ValueFound: false,
174
- Def: option,
175
- }
176
-}
177
-
178
-// Options returns a copy of the option map
179
-func (r *request) Options() cmdkit.OptMap {
180
- output := make(cmdkit.OptMap)
181
- for k, v := range r.options {
182
- output[k] = v
183
- }
184
- return output
185
-}
186
-
187
-// SetOption sets the value of the option for given name.
188
-func (r *request) SetOption(name string, val interface{}) {
189
- // find the option with the specified name
190
- option, found := r.optionDefs[name]
191
- if !found {
192
- return
193
- }
194
-
195
- // try all the possible names, if we already have a value then set over it
196
- for _, n := range option.Names() {
197
- _, found := r.options[n]
198
- if found {
199
- r.options[n] = val
200
- return
201
- }
202
- }
203
-
204
- r.options[name] = val
205
-}
206
-
207
-// SetOptions sets the option values, unsetting any values that were previously set
208
-func (r *request) SetOptions(opts cmdkit.OptMap) error {
209
- r.options = opts
210
- return r.ConvertOptions()
211
-}
212
-
213
-func (r *request) StringArguments() []string {
214
- return r.arguments
215
-}
216
-
217
-// Arguments returns the arguments slice
218
-func (r *request) Arguments() []string {
219
- if r.haveVarArgsFromStdin() {
220
- err := r.VarArgs(func(s string) error {
221
- r.arguments = append(r.arguments, s)
222
- return nil
223
- })
224
- if err != nil && err != io.EOF {
225
- log.Error(err)
226
- }
227
- }
228
-
229
- return r.arguments
230
-}
231
-
232
-func (r *request) SetArguments(args []string) {
233
- r.arguments = args
234
-}
235
-
236
-func (r *request) Files() files.File {
237
- return r.files
238
-}
239
-
240
-func (r *request) SetFiles(f files.File) {
241
- r.files = f
242
-}
243
-
244
-func (r *request) Context() context.Context {
245
- return r.rctx
246
-}
247
-
248
-func (r *request) haveVarArgsFromStdin() bool {
249
- // we expect varargs if we have a string argument that supports stdin
250
- // and not arguments to satisfy it
251
- if len(r.cmd.Arguments) == 0 {
252
- return false
253
- }
254
-
255
- last := r.cmd.Arguments[len(r.cmd.Arguments)-1]
256
- return last.SupportsStdin && last.Type == cmdkit.ArgString && (last.Required || last.Variadic) &&
257
- len(r.arguments) < len(r.cmd.Arguments)
258
-}
259
-
260
-// VarArgs can be used when you want string arguments as input
261
-// and also want to be able to handle them in a streaming fashion
262
-func (r *request) VarArgs(f func(string) error) error {
263
- if len(r.arguments) >= len(r.cmd.Arguments) {
264
- for _, arg := range r.arguments[len(r.cmd.Arguments)-1:] {
265
- err := f(arg)
266
- if err != nil {
267
- return err
268
- }
269
- }
270
-
271
- return nil
272
- }
273
-
274
- if r.files == nil {
275
- log.Warning("expected more arguments from stdin")
276
- return nil
277
- }
278
-
279
- fi, err := r.files.NextFile()
280
- if err != nil {
281
- return err
282
- }
283
-
284
- var any bool
285
- scan := bufio.NewScanner(fi)
286
- for scan.Scan() {
287
- any = true
288
- err := f(scan.Text())
289
- if err != nil {
290
- return err
291
- }
292
- }
293
- if !any {
294
- return f("")
295
- }
296
-
297
- return nil
298
-}
299
-
300
-func (r *request) InvocContext() *Context {
301
- return &r.ctx
302
-}
303
-
304
-func (r *request) SetInvocContext(ctx Context) {
305
- r.ctx = ctx
306
-}
307
-
308
-func (r *request) Command() *Command {
309
- return r.cmd
310
-}
311
-
312
-type converter func(string) (interface{}, error)
313
-
314
-var converters = map[reflect.Kind]converter{
315
- cmdkit.Bool: func(v string) (interface{}, error) {
316
- if v == "" {
317
- return true, nil
318
- }
319
- return strconv.ParseBool(v)
320
- },
321
- cmdkit.Int: func(v string) (interface{}, error) {
322
- val, err := strconv.ParseInt(v, 0, 32)
323
- if err != nil {
324
- return nil, err
325
- }
326
- return int(val), err
327
- },
328
- cmdkit.Uint: func(v string) (interface{}, error) {
329
- val, err := strconv.ParseUint(v, 0, 32)
330
- if err != nil {
331
- return nil, err
332
- }
333
- return int(val), err
334
- },
335
- cmdkit.Float: func(v string) (interface{}, error) {
336
- return strconv.ParseFloat(v, 64)
337
- },
338
-}
339
-
340
-func (r *request) Values() map[string]interface{} {
341
- return r.values
342
-}
343
-
344
-func (r *request) Stdin() io.Reader {
345
- return r.stdin
346
-}
347
-
348
-func (r *request) ConvertOptions() error {
349
- for k, v := range r.options {
350
- opt, ok := r.optionDefs[k]
351
- if !ok {
352
- continue
353
- }
354
-
355
- kind := reflect.TypeOf(v).Kind()
356
- if kind != opt.Type() {
357
- if kind == cmdkit.String {
358
- convert := converters[opt.Type()]
359
- str, ok := v.(string)
360
- if !ok {
361
- return u.ErrCast()
362
- }
363
- val, err := convert(str)
364
- if err != nil {
365
- value := fmt.Sprintf("value '%v'", v)
366
- if len(str) == 0 {
367
- value = "empty value"
368
- }
369
- return fmt.Errorf("Could not convert %s to type '%s' (for option '-%s')",
370
- value, opt.Type().String(), k)
371
- }
372
- r.options[k] = val
373
-
374
- } else {
375
- return fmt.Errorf("Option '%s' should be type '%s', but got type '%s'",
376
- k, opt.Type().String(), kind.String())
377
- }
378
- } else {
379
- r.options[k] = v
380
- }
381
-
382
- for _, name := range opt.Names() {
383
- if _, ok := r.options[name]; name != k && ok {
384
- return fmt.Errorf("Duplicate command options were provided ('%s' and '%s')",
385
- k, name)
386
- }
387
- }
388
- }
389
-
390
- return nil
391
-}
392
-
393
-// NewEmptyRequest initializes an empty request
394
-func NewEmptyRequest() (Request, error) {
395
- return NewRequest(nil, nil, nil, nil, nil, nil)
396
-}
397
-
398
-// NewRequest returns a request initialized with given arguments
399
-// An non-nil error will be returned if the provided option values are invalid
400
-func NewRequest(path []string, opts cmdkit.OptMap, args []string, file files.File, cmd *Command, optDefs map[string]cmdkit.Option) (Request, error) {
401
- if opts == nil {
402
- opts = make(cmdkit.OptMap)
403
- }
404
- if optDefs == nil {
405
- optDefs = make(map[string]cmdkit.Option)
406
- }
407
-
408
- ctx := Context{}
409
- values := make(map[string]interface{})
410
- req := &request{
411
- path: path,
412
- options: opts,
413
- arguments: args,
414
- files: file,
415
- cmd: cmd,
416
- ctx: ctx,
417
- optionDefs: optDefs,
418
- values: values,
419
- stdin: os.Stdin,
420
- }
421
- err := req.ConvertOptions()
422
- if err != nil {
423
- return nil, err
424
- }
425
-
426
- return req, nil
108
}
commands/response.go
-181
@@ -1,15 +1,8 @@
1
package commands
2
3
import (
4
- "bytes"
5
- "encoding/json"
6
- "encoding/xml"
7
- "fmt"
4
"io"
9
- "os"
10
- "strings"
5
12
- cmds "gx/ipfs/QmabLouZTZwhfALuBcssPvkzhbYGMb4394huT7HY4LQ6d3/go-ipfs-cmds"
6
cmdkit "gx/ipfs/QmceUdzxkimdYsgtX733uNgzf1DLHyBKN6ehGSp85ayppM/go-ipfs-cmdkit"
7
)
8
@@ -28,50 +21,6 @@ const (
21
// TODO: support more encoding types
22
)
23
31
-func marshalJson(value interface{}) (io.Reader, error) {
32
- b, err := json.Marshal(value)
33
- if err != nil {
34
- return nil, err
35
- }
36
- b = append(b, '\n')
37
- return bytes.NewReader(b), nil
38
-}
39
-
40
-var marshallers = map[EncodingType]Marshaler{
41
- JSON: func(res Response) (io.Reader, error) {
42
- ch, ok := res.Output().(<-chan interface{})
43
- if ok {
44
- return &ChannelMarshaler{
45
- Channel: ch,
46
- Marshaler: marshalJson,
47
- Res: res,
48
- }, nil
49
- }
50
-
51
- var value interface{}
52
- if res.Error() != nil {
53
- value = res.Error()
54
- } else {
55
- value = res.Output()
56
- }
57
- return marshalJson(value)
58
- },
59
- XML: func(res Response) (io.Reader, error) {
60
- var value interface{}
61
- if res.Error() != nil {
62
- value = res.Error()
63
- } else {
64
- value = res.Output()
65
- }
66
-
67
- b, err := xml.Marshal(value)
68
- if err != nil {
69
- return nil, err
70
- }
71
- return bytes.NewReader(b), nil
72
- },
73
-}
74
-
24
// Response is the result of a command request. Handlers write to the response,
25
// setting Error or Value. Response is returned to the client.
26
type Response interface {
@@ -104,133 +53,3 @@ type Response interface {
53
Stdout() io.Writer
54
Stderr() io.Writer
55
}
107
-
108
-type response struct {
109
- req Request
110
- err *cmdkit.Error
111
- value interface{}
112
- out io.Reader
113
- length uint64
114
- stdout io.Writer
115
- stderr io.Writer
116
- closer io.Closer
117
-}
118
-
119
-func (r *response) Request() Request {
120
- return r.req
121
-}
122
-
123
-func (r *response) Output() interface{} {
124
- return r.value
125
-}
126
-
127
-func (r *response) SetOutput(v interface{}) {
128
- r.value = v
129
-}
130
-
131
-func (r *response) Length() uint64 {
132
- return r.length
133
-}
134
-
135
-func (r *response) SetLength(l uint64) {
136
- r.length = l
137
-}
138
-
139
-func (r *response) Error() *cmdkit.Error {
140
- return r.err
141
-}
142
-
143
-func (r *response) SetError(err error, code cmdkit.ErrorType) {
144
- r.err = &cmdkit.Error{Message: err.Error(), Code: code}
145
-}
146
-
147
-func (r *response) Marshal() (io.Reader, error) {
148
- if r.err == nil && r.value == nil {
149
- return bytes.NewReader([]byte{}), nil
150
- }
151
-
152
- enc, found, err := r.req.Option(cmds.EncLong).String()
153
- if err != nil {
154
- return nil, err
155
- }
156
- if !found {
157
- return nil, fmt.Errorf("No encoding type was specified")
158
- }
159
- encType := EncodingType(strings.ToLower(enc))
160
-
161
- // Special case: if text encoding and an error, just print it out.
162
- if encType == Text && r.Error() != nil {
163
- return strings.NewReader(r.Error().Error()), nil
164
- }
165
-
166
- var marshaller Marshaler
167
- if r.req.Command() != nil && r.req.Command().Marshalers != nil {
168
- marshaller = r.req.Command().Marshalers[encType]
169
- }
170
- if marshaller == nil {
171
- var ok bool
172
- marshaller, ok = marshallers[encType]
173
- if !ok {
174
- return nil, fmt.Errorf("No marshaller found for encoding type '%s'", enc)
175
- }
176
- }
177
-
178
- output, err := marshaller(r)
179
- if err != nil {
180
- return nil, err
181
- }
182
- if output == nil {
183
- return bytes.NewReader([]byte{}), nil
184
- }
185
- return output, nil
186
-}
187
-
188
-// Reader returns an `io.Reader` representing marshalled output of this Response
189
-// Note that multiple calls to this will return a reference to the same io.Reader
190
-func (r *response) Reader() (io.Reader, error) {
191
- if r.out == nil {
192
- if out, ok := r.value.(io.Reader); ok {
193
- // if command returned a io.Reader, use that as our reader
194
- r.out = out
195
-
196
- } else {
197
- // otherwise, use the response marshaler output
198
- marshalled, err := r.Marshal()
199
- if err != nil {
200
- return nil, err
201
- }
202
-
203
- r.out = marshalled
204
- }
205
- }
206
-
207
- return r.out, nil
208
-}
209
-
210
-func (r *response) Close() error {
211
- if r.closer != nil {
212
- return r.closer.Close()
213
- }
214
- return nil
215
-}
216
-
217
-func (r *response) SetCloser(c io.Closer) {
218
- r.closer = c
219
-}
220
-
221
-func (r *response) Stdout() io.Writer {
222
- return r.stdout
223
-}
224
-
225
-func (r *response) Stderr() io.Writer {
226
- return r.stderr
227
-}
228
-
229
-// NewResponse returns a response to match given Request
230
-func NewResponse(req Request) Response {
231
- return &response{
232
- req: req,
233
- stdout: os.Stdout,
234
- stderr: os.Stderr,
235
- }
236
-}
commands/response_test.go
deleted
-70
@@ -1,70 +0,0 @@
1
-package commands
2
-
3
-import (
4
- "bytes"
5
- "fmt"
6
- "strings"
7
- "testing"
8
-
9
- cmds "gx/ipfs/QmabLouZTZwhfALuBcssPvkzhbYGMb4394huT7HY4LQ6d3/go-ipfs-cmds"
10
- cmdkit "gx/ipfs/QmceUdzxkimdYsgtX733uNgzf1DLHyBKN6ehGSp85ayppM/go-ipfs-cmdkit"
11
-)
12
-
13
-type TestOutput struct {
14
- Foo, Bar string
15
- Baz int
16
-}
17
-
18
-func TestMarshalling(t *testing.T) {
19
- cmd := &Command{}
20
- opts, _ := cmd.GetOptions(nil)
21
-
22
- req, _ := NewRequest(nil, nil, nil, nil, nil, opts)
23
-
24
- res := NewResponse(req)
25
- res.SetOutput(TestOutput{"beep", "boop", 1337})
26
-
27
- _, err := res.Marshal()
28
- if err == nil {
29
- t.Error("Should have failed (no encoding type specified in request)")
30
- }
31
-
32
- req.SetOption(cmds.EncLong, JSON)
33
-
34
- reader, err := res.Marshal()
35
- if err != nil {
36
- t.Error(err, "Should have passed")
37
- }
38
- buf := new(bytes.Buffer)
39
- buf.ReadFrom(reader)
40
- output := buf.String()
41
- if removeWhitespace(output) != "{\"Foo\":\"beep\",\"Bar\":\"boop\",\"Baz\":1337}" {
42
- t.Error("Incorrect JSON output")
43
- }
44
-
45
- res.SetError(fmt.Errorf("Oops!"), cmdkit.ErrClient)
46
- reader, err = res.Marshal()
47
- if err != nil {
48
- t.Error("Should have passed")
49
- }
50
- buf.Reset()
51
- buf.ReadFrom(reader)
52
- output = buf.String()
53
- fmt.Println(removeWhitespace(output))
54
- if removeWhitespace(output) != `{"Message":"Oops!","Code":1,"Type":"error"}` {
55
- t.Error("Incorrect JSON output")
56
- }
57
-}
58
-
59
-func TestErrTypeOrder(t *testing.T) {
60
- if cmdkit.ErrNormal != 0 || cmdkit.ErrClient != 1 || cmdkit.ErrImplementation != 2 || cmdkit.ErrNotFound != 3 {
61
- t.Fatal("ErrType order is wrong")
62
- }
63
-}
64
-
65
-func removeWhitespace(input string) string {
66
- input = strings.Replace(input, " ", "", -1)
67
- input = strings.Replace(input, "\t", "", -1)
68
- input = strings.Replace(input, "\n", "", -1)
69
- return strings.Replace(input, "\r", "", -1)
70
-}