From 7b4de230eb3d33c503f7b42211c9ffd2b337a38f Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Tue, 20 Jan 2015 17:58:50 -0800 Subject: [PATCH] commands: Refactored Command#Run function signature to (req Request, res Response) --- cmd/ipfs/daemon.go | 38 ++++++++++++++------- cmd/ipfs/init.go | 15 ++++++--- cmd/ipfs/tour.go | 38 +++++++++++---------- commands/command.go | 18 +++------- commands/command_test.go | 4 +-- core/commands/add.go | 8 ++--- core/commands/block.go | 41 ++++++++++++++--------- core/commands/bootstrap.go | 51 +++++++++++++++++++---------- core/commands/cat.go | 10 +++--- core/commands/commands.go | 4 +-- core/commands/config.go | 57 +++++++++++++++++++++++--------- core/commands/diag.go | 36 ++++++++++++++------ core/commands/id.go | 33 ++++++++++++++----- core/commands/log.go | 11 ++++--- core/commands/ls.go | 10 +++--- core/commands/mount_unix.go | 22 ++++++++----- core/commands/mount_windows.go | 4 +-- core/commands/object.go | 60 ++++++++++++++++++++++------------ core/commands/pin.go | 39 +++++++++++++--------- core/commands/ping.go | 16 +++++---- core/commands/publish.go | 19 +++++++---- core/commands/refs.go | 32 +++++++++++------- core/commands/repo.go | 12 ++++--- core/commands/resolve.go | 16 +++++---- core/commands/swarm.go | 23 ++++++++----- core/commands/update.go | 39 +++++++++++++++++----- core/commands/version.go | 6 ++-- 27 files changed, 426 insertions(+), 236 deletions(-) diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 0e83e9a8a..471e14778 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -47,13 +47,14 @@ the daemon. Run: daemonFunc, } -func daemonFunc(req cmds.Request) (interface{}, error) { +func daemonFunc(req cmds.Request, res cmds.Response) { // first, whether user has provided the initialization flag. we may be // running in an uninitialized state. initialize, _, err := req.Option(initOptionKwd).Bool() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if initialize { @@ -64,7 +65,8 @@ func daemonFunc(req cmds.Request) (interface{}, error) { if !util.FileExists(req.Context().ConfigRoot) { err := initWithDefaults(req.Context().ConfigRoot) if err != nil { - return nil, debugerror.Wrap(err) + res.SetError(debugerror.Wrap(err), cmds.ErrNormal) + return } } } @@ -77,14 +79,16 @@ func daemonFunc(req cmds.Request) (interface{}, error) { ctx := req.Context() cfg, err := ctx.GetConfig() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } // acquire the repo lock _before_ constructing a node. we need to make // sure we are permitted to access the resources (datastore, etc.) repo := fsrepo.At(req.Context().ConfigRoot) if err := repo.Open(); err != nil { - return nil, debugerror.Errorf("Couldn't obtain lock. Is another daemon already running?") + res.SetError(debugerror.Errorf("Couldn't obtain lock. Is another daemon already running?"), cmds.ErrNormal) + return } defer repo.Close() @@ -93,13 +97,15 @@ func daemonFunc(req cmds.Request) (interface{}, error) { ctx.Online = true node, err := ctx.GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } // verify api address is valid multiaddr apiMaddr, err := ma.NewMultiaddr(cfg.Addresses.API) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } var gatewayMaddr ma.Multiaddr @@ -115,12 +121,14 @@ func daemonFunc(req cmds.Request) (interface{}, error) { // mount if the user provided the --mount flag mount, _, err := req.Option(mountKwd).Bool() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if mount { fsdir, found, err := req.Option(ipfsMountKwd).String() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if !found { fsdir = cfg.Mounts.IPFS @@ -128,7 +136,8 @@ func daemonFunc(req cmds.Request) (interface{}, error) { nsdir, found, err := req.Option(ipnsMountKwd).String() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if !found { nsdir = cfg.Mounts.IPNS @@ -136,7 +145,8 @@ func daemonFunc(req cmds.Request) (interface{}, error) { err = commands.Mount(node, fsdir, nsdir) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } fmt.Printf("IPFS mounted at: %s\n", fsdir) fmt.Printf("IPNS mounted at: %s\n", nsdir) @@ -156,5 +166,9 @@ func daemonFunc(req cmds.Request) (interface{}, error) { corehttp.WebUIOption, corehttp.GatewayOption, } - return nil, corehttp.ListenAndServe(node, apiMaddr, opts...) + err = corehttp.ListenAndServe(node, apiMaddr, opts...) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } } diff --git a/cmd/ipfs/init.go b/cmd/ipfs/init.go index ec8025bc0..cdb61f2c4 100644 --- a/cmd/ipfs/init.go +++ b/cmd/ipfs/init.go @@ -39,22 +39,29 @@ var initCmd = &cmds.Command{ // name of the file? // TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs"), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { force, _, err := req.Option("f").Bool() // if !found, it's okay force == false if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } nBitsForKeypair, bitsOptFound, err := req.Option("b").Int() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if !bitsOptFound { nBitsForKeypair = nBitsForKeypairDefault } - return doInit(req.Context().ConfigRoot, force, nBitsForKeypair) + output, err := doInit(req.Context().ConfigRoot, force, nBitsForKeypair) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) }, } diff --git a/cmd/ipfs/tour.go b/cmd/ipfs/tour.go index 168bacc9c..9a5277301 100644 --- a/cmd/ipfs/tour.go +++ b/cmd/ipfs/tour.go @@ -36,11 +36,12 @@ IPFS very quickly. To start, run: Run: tourRunFunc, } -func tourRunFunc(req cmds.Request) (interface{}, error) { +func tourRunFunc(req cmds.Request, res cmds.Response) { cfg, err := req.Context().GetConfig() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } id := tour.TopicID(cfg.Tour.Last) @@ -64,11 +65,10 @@ func tourRunFunc(req cmds.Request) (interface{}, error) { fmt.Fprintln(&w, "") fprintTourList(&w, tour.TopicID(cfg.Tour.Last)) - return nil, nil + return } fprintTourShow(&w, t) - return nil, nil } var cmdIpfsTourNext = &cmds.Command{ @@ -76,21 +76,24 @@ var cmdIpfsTourNext = &cmds.Command{ Tagline: "Show the next IPFS Tour topic", }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { var w bytes.Buffer path := req.Context().ConfigRoot cfg, err := req.Context().GetConfig() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } id := tour.NextTopic(tour.TopicID(cfg.Tour.Last)) topic, err := tourGet(id) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if err := fprintTourShow(&w, topic); err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } // topic changed, not last. write it out. @@ -98,12 +101,12 @@ var cmdIpfsTourNext = &cmds.Command{ cfg.Tour.Last = string(id) err := writeConfig(path, cfg) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } } w.WriteTo(os.Stdout) - return nil, nil }, } @@ -112,19 +115,20 @@ var cmdIpfsTourRestart = &cmds.Command{ Tagline: "Restart the IPFS Tour", }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { path := req.Context().ConfigRoot cfg, err := req.Context().GetConfig() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } cfg.Tour.Last = "" err = writeConfig(path, cfg) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return nil, nil }, } @@ -133,16 +137,16 @@ var cmdIpfsTourList = &cmds.Command{ Tagline: "Show a list of IPFS Tour topics", }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { cfg, err := req.Context().GetConfig() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } var w bytes.Buffer fprintTourList(&w, tour.TopicID(cfg.Tour.Last)) w.WriteTo(os.Stdout) - return nil, nil }, } diff --git a/commands/command.go b/commands/command.go index f79bf31c0..f52ce7f06 100644 --- a/commands/command.go +++ b/commands/command.go @@ -14,7 +14,7 @@ var log = u.Logger("command") // Function is the type of function that Commands use. // It reads from the Request, and writes results to the Response. -type Function func(Request) (interface{}, error) +type Function func(Request, Response) // Marshaler is a function that takes in a Response, and returns an io.Reader // (or an error on failure) @@ -95,21 +95,12 @@ func (c *Command) Call(req Request) Response { return res } - output, err := cmd.Run(req) - if err != nil { - // if returned error is a commands.Error, use its error code - // otherwise, just default the code to ErrNormal - switch e := err.(type) { - case *Error: - res.SetError(e, e.Code) - case Error: - res.SetError(e, e.Code) - default: - res.SetError(err, ErrNormal) - } + cmd.Run(req, res) + if res.Error() != nil { return res } + output := res.Output() isChan := false actualType := reflect.TypeOf(output) if actualType != nil { @@ -140,7 +131,6 @@ func (c *Command) Call(req Request) Response { } } - res.SetOutput(output) return res } diff --git a/commands/command_test.go b/commands/command_test.go index 4fcc48bd8..a5cad4d02 100644 --- a/commands/command_test.go +++ b/commands/command_test.go @@ -2,8 +2,8 @@ package commands import "testing" -func noop(req Request) (interface{}, error) { - return nil, nil +func noop(req Request, res Response) { + return } func TestOptionValidation(t *testing.T) { diff --git a/core/commands/add.go b/core/commands/add.go index 61c412a04..0e82e473f 100644 --- a/core/commands/add.go +++ b/core/commands/add.go @@ -44,13 +44,15 @@ remains to be implemented. cmds.OptionRecursivePath, // a builtin option that allows recursive paths (-r, --recursive) cmds.BoolOption("quiet", "q", "Write minimal output"), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } outChan := make(chan interface{}) + res.SetOutput((<-chan interface{})(outChan)) go func() { defer close(outChan) @@ -67,8 +69,6 @@ remains to be implemented. } } }() - - return outChan, nil }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { diff --git a/core/commands/block.go b/core/commands/block.go index 2df004407..3f1563307 100644 --- a/core/commands/block.go +++ b/core/commands/block.go @@ -2,6 +2,7 @@ package commands import ( "bytes" + "errors" "fmt" "io" "io/ioutil" @@ -57,16 +58,17 @@ on raw ipfs blocks. It outputs the following to stdout: Arguments: []cmds.Argument{ cmds.StringArg("key", true, false, "The base58 multihash of an existing block to get").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { b, err := getBlockForKey(req, req.Arguments()[0]) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return &BlockStat{ + res.SetOutput(&BlockStat{ Key: b.Key().Pretty(), Size: len(b.Data), - }, nil + }) }, Type: BlockStat{}, Marshalers: cmds.MarshalerMap{ @@ -89,13 +91,14 @@ It outputs to stdout, and is a base58 encoded multihash. Arguments: []cmds.Argument{ cmds.StringArg("key", true, false, "The base58 multihash of an existing block to get").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { b, err := getBlockForKey(req, req.Arguments()[0]) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return bytes.NewReader(b.Data), nil + res.SetOutput(bytes.NewReader(b.Data)) }, } @@ -111,25 +114,29 @@ It reads from stdin, and is a base58 encoded multihash. Arguments: []cmds.Argument{ cmds.FileArg("data", true, false, "The data to be stored as an IPFS block").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } file, err := req.Files().NextFile() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } data, err := ioutil.ReadAll(file) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } err = file.Close() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } b := blocks.NewBlock(data) @@ -137,13 +144,14 @@ It reads from stdin, and is a base58 encoded multihash. k, err := n.Blocks.AddBlock(b) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return &BlockStat{ + res.SetOutput(&BlockStat{ Key: k.String(), Size: len(data), - }, nil + }) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { @@ -160,7 +168,7 @@ func getBlockForKey(req cmds.Request, key string) (*blocks.Block, error) { } if !u.IsValidHash(key) { - return nil, cmds.Error{"Not a valid hash", cmds.ErrClient} + return nil, errors.New("Not a valid hash") } h, err := mh.FromB58String(key) @@ -173,6 +181,7 @@ func getBlockForKey(req cmds.Request, key string) (*blocks.Block, error) { if err != nil { return nil, err } + log.Debugf("ipfs block: got block with key: %q", b.Key()) return b, nil } diff --git a/core/commands/bootstrap.go b/core/commands/bootstrap.go index a84682a8c..78397ef9a 100644 --- a/core/commands/bootstrap.go +++ b/core/commands/bootstrap.go @@ -76,29 +76,33 @@ in the bootstrap list). cmds.BoolOption("default", "add default bootstrap nodes"), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { inputPeers, err := config.ParseBootstrapPeers(req.Arguments()) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } r := fsrepo.At(req.Context().ConfigRoot) if err := r.Open(); err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } defer r.Close() cfg := r.Config() deflt, _, err := req.Option("default").Bool() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if deflt { // parse separately for meaningful, correct error. defltPeers, err := DefaultBootstrapPeers() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } inputPeers = append(inputPeers, defltPeers...) @@ -106,14 +110,16 @@ in the bootstrap list). added, err := bootstrapAdd(r, cfg, inputPeers) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if len(inputPeers) == 0 { - return nil, cmds.ClientError("no bootstrap peers to add") + res.SetError(errors.New("no bootstrap peers to add"), cmds.ErrClient) + return } - return &BootstrapOutput{added}, nil + res.SetOutput(&BootstrapOutput{added}) }, Type: BootstrapOutput{}, Marshalers: cmds.MarshalerMap{ @@ -125,7 +131,11 @@ in the bootstrap list). var buf bytes.Buffer err := bootstrapWritePeers(&buf, "added ", v.Peers) - return &buf, err + if err != nil { + return nil, err + } + + return &buf, nil }, }, } @@ -143,22 +153,25 @@ var bootstrapRemoveCmd = &cmds.Command{ Options: []cmds.Option{ cmds.BoolOption("all", "Remove all bootstrap peers."), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { input, err := config.ParseBootstrapPeers(req.Arguments()) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } r := fsrepo.At(req.Context().ConfigRoot) if err := r.Open(); err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } defer r.Close() cfg := r.Config() all, _, err := req.Option("all").Bool() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } var removed []config.BootstrapPeer @@ -168,10 +181,11 @@ var bootstrapRemoveCmd = &cmds.Command{ removed, err = bootstrapRemove(r, cfg, input) } if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return &BootstrapOutput{removed}, nil + res.SetOutput(&BootstrapOutput{removed}) }, Type: BootstrapOutput{}, Marshalers: cmds.MarshalerMap{ @@ -194,14 +208,15 @@ var bootstrapListCmd = &cmds.Command{ ShortDescription: "Peers are output in the format '/'.", }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { cfg, err := req.Context().GetConfig() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } peers := cfg.Bootstrap - return &BootstrapOutput{peers}, nil + res.SetOutput(&BootstrapOutput{peers}) }, Type: BootstrapOutput{}, Marshalers: cmds.MarshalerMap{ diff --git a/core/commands/cat.go b/core/commands/cat.go index fe67cdb91..208908937 100644 --- a/core/commands/cat.go +++ b/core/commands/cat.go @@ -20,21 +20,23 @@ it contains. Arguments: []cmds.Argument{ cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to be outputted").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { node, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } readers := make([]io.Reader, 0, len(req.Arguments())) readers, err = cat(node, req.Arguments()) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } reader := io.MultiReader(readers...) - return reader, nil + res.SetOutput(reader) }, } diff --git a/core/commands/commands.go b/core/commands/commands.go index df447d290..b0e38c902 100644 --- a/core/commands/commands.go +++ b/core/commands/commands.go @@ -22,9 +22,9 @@ func CommandsCmd(root *cmds.Command) *cmds.Command { ShortDescription: `Lists all available commands (and subcommands) and exits.`, }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { root := cmd2outputCmd("ipfs", root) - return &root, nil + res.SetOutput(&root) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { diff --git a/core/commands/config.go b/core/commands/config.go index 267b33177..33d56cf0f 100644 --- a/core/commands/config.go +++ b/core/commands/config.go @@ -57,23 +57,34 @@ Set the value of the 'datastore.path' key: cmds.StringArg("key", true, false, "The key of the config entry (e.g. \"Addresses.API\")"), cmds.StringArg("value", false, false, "The value to set the config entry to"), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { args := req.Arguments() key := args[0] r := fsrepo.At(req.Context().ConfigRoot) if err := r.Open(); err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } defer r.Close() var value string if len(args) == 2 { value = args[1] - return setConfig(r, key, value) + output, err := setConfig(r, key, value) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) } else { - return getConfig(r, key) + output, err := getConfig(r, key) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) } }, Marshalers: cmds.MarshalerMap{ @@ -117,13 +128,19 @@ included in the output of this command. `, }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { filename, err := config.Filename(req.Context().ConfigRoot) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return showConfig(filename) + output, err := showConfig(filename) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) }, } @@ -136,19 +153,23 @@ variable set to your preferred text editor. `, }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { filename, err := config.Filename(req.Context().ConfigRoot) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return nil, editConfig(filename) + err = editConfig(filename) + if err != nil { + res.SetError(err, cmds.ErrNormal) + } }, } var configReplaceCmd = &cmds.Command{ Helptext: cmds.HelpText{ - Tagline: "Replaces the config with ", + Tagline: "Replaces the config with `file>", ShortDescription: ` Make sure to back up the config file first if neccessary, this operation can't be undone. @@ -158,20 +179,26 @@ can't be undone. Arguments: []cmds.Argument{ cmds.FileArg("file", true, false, "The file to use as the new config"), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { r := fsrepo.At(req.Context().ConfigRoot) if err := r.Open(); err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } defer r.Close() file, err := req.Files().NextFile() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } defer file.Close() - return nil, replaceConfig(r, file) + err = replaceConfig(r, file) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } }, } diff --git a/core/commands/diag.go b/core/commands/diag.go index 98790f674..28b3673a3 100644 --- a/core/commands/diag.go +++ b/core/commands/diag.go @@ -2,6 +2,7 @@ package commands import ( "bytes" + "errors" "io" "strings" "text/template" @@ -63,50 +64,65 @@ connected peers and latencies between them. cmds.StringOption("vis", "output vis. one of: "+strings.Join(visFmts, ", ")), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if !n.OnlineMode() { - return nil, errNotOnline + res.SetError(errNotOnline, cmds.ErrClient) + return } vis, _, err := req.Option("vis").String() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } timeoutS, _, err := req.Option("timeout").String() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } timeout := DefaultDiagnosticTimeout if timeoutS != "" { t, err := time.ParseDuration(timeoutS) if err != nil { - return nil, cmds.ClientError("error parsing timeout") + res.SetError(errors.New("error parsing timeout"), cmds.ErrNormal) + return } timeout = t } info, err := n.Diagnostics.GetDiagnostic(timeout) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } switch vis { case visD3: - return bytes.NewReader(diag.GetGraphJson(info)), nil + res.SetOutput(bytes.NewReader(diag.GetGraphJson(info))) case visDot: var buf bytes.Buffer w := diag.DotWriter{W: &buf} err := w.WriteGraph(info) - return io.Reader(&buf), err + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(io.Reader(&buf)) } - return stdDiagOutputMarshal(standardDiagOutput(info)) + output, err := stdDiagOutputMarshal(standardDiagOutput(info)) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) }, } diff --git a/core/commands/id.go b/core/commands/id.go index 0452a2fdf..7d47465d9 100644 --- a/core/commands/id.go +++ b/core/commands/id.go @@ -45,37 +45,54 @@ if no peer is specified, prints out local peers info. Arguments: []cmds.Argument{ cmds.StringArg("peerid", false, false, "peer.ID of node to look up").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { node, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if len(req.Arguments()) == 0 { - return printPeer(node.Peerstore, node.Identity) + output, err := printPeer(node.Peerstore, node.Identity) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) + return } pid := req.Arguments()[0] id := peer.ID(b58.Decode(pid)) if len(id) == 0 { - return nil, cmds.ClientError("Invalid peer id") + res.SetError(cmds.ClientError("Invalid peer id"), cmds.ErrClient) + return } ctx, _ := context.WithTimeout(context.TODO(), time.Second*5) // TODO handle offline mode with polymorphism instead of conditionals if !node.OnlineMode() { - return nil, errors.New(offlineIdErrorMessage) + res.SetError(errors.New(offlineIdErrorMessage), cmds.ErrClient) + return } p, err := node.Routing.FindPeer(ctx, id) if err == kb.ErrLookupFailure { - return nil, errors.New(offlineIdErrorMessage) + res.SetError(errors.New(offlineIdErrorMessage), cmds.ErrClient) + return } if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return printPeer(node.Peerstore, p.ID) + + output, err := printPeer(node.Peerstore, p.ID) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { diff --git a/core/commands/log.go b/core/commands/log.go index f202d1d3e..34e33730e 100644 --- a/core/commands/log.go +++ b/core/commands/log.go @@ -47,7 +47,7 @@ output of a running daemon. cmds.StringArg("subsystem", true, false, fmt.Sprintf("the subsystem logging identifier. Use '%s' for all subsystems.", logAllKeyword)), cmds.StringArg("level", true, false, "one of: debug, info, notice, warning, error, critical"), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { args := req.Arguments() subsystem, level := args[0], args[1] @@ -57,12 +57,13 @@ output of a running daemon. } if err := u.SetLogLevel(subsystem, level); err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } s := fmt.Sprintf("Changed log level of '%s' to '%s'", subsystem, level) log.Info(s) - return &MessageOutput{s}, nil + res.SetOutput(&MessageOutput{s}) }, Marshalers: cmds.MarshalerMap{ cmds.Text: MessageTextMarshaler, @@ -78,7 +79,7 @@ var logTailCmd = &cmds.Command{ `, }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { path := fmt.Sprintf("%s/logs/events.log", req.Context().ConfigRoot) outChan := make(chan interface{}) @@ -108,7 +109,7 @@ var logTailCmd = &cmds.Command{ } }() - return (<-chan interface{})(outChan), nil + res.SetOutput((<-chan interface{})(outChan)) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { diff --git a/core/commands/ls.go b/core/commands/ls.go index 43b38339a..3901dfd83 100644 --- a/core/commands/ls.go +++ b/core/commands/ls.go @@ -37,10 +37,11 @@ it contains, with the following format: Arguments: []cmds.Argument{ cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { node, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } paths := req.Arguments() @@ -49,7 +50,8 @@ it contains, with the following format: for _, path := range paths { dagnode, err := node.Resolver.ResolvePath(path) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } dagnodes = append(dagnodes, dagnode) } @@ -69,7 +71,7 @@ it contains, with the following format: } } - return &LsOutput{output}, nil + res.SetOutput(&LsOutput{output}) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { diff --git a/core/commands/mount_unix.go b/core/commands/mount_unix.go index d07a513b9..966463176 100644 --- a/core/commands/mount_unix.go +++ b/core/commands/mount_unix.go @@ -90,25 +90,29 @@ baz // TODO longform cmds.StringOption("n", "The path where IPNS should be mounted"), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { cfg, err := req.Context().GetConfig() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } node, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } // error if we aren't running node in online mode if !node.OnlineMode() { - return nil, errNotOnline + res.SetError(errNotOnline, cmds.ErrClient) + return } fsdir, found, err := req.Option("f").String() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if !found { fsdir = cfg.Mounts.IPFS // use default value @@ -117,7 +121,8 @@ baz // get default mount points nsdir, found, err := req.Option("n").String() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if !found { nsdir = cfg.Mounts.IPNS // NB: be sure to not redeclare! @@ -125,13 +130,14 @@ baz err = Mount(node, fsdir, nsdir) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } var output config.Mounts output.IPFS = fsdir output.IPNS = nsdir - return &output, nil + res.SetOutput(&output) }, Type: config.Mounts{}, Marshalers: cmds.MarshalerMap{ diff --git a/core/commands/mount_windows.go b/core/commands/mount_windows.go index 01bcc698c..1b796c9ef 100644 --- a/core/commands/mount_windows.go +++ b/core/commands/mount_windows.go @@ -13,8 +13,8 @@ var MountCmd = &cmds.Command{ ShortDescription: "Not yet implemented on Windows. :(", }, - Run: func(req cmds.Request) (interface{}, error) { - return errors.New("Mount isn't compatible with Windows yet"), nil + Run: func(req cmds.Request, res cmds.Response) { + res.SetError(errors.New("Mount isn't compatible with Windows yet"), cmds.ErrNormal) }, } diff --git a/core/commands/object.go b/core/commands/object.go index e977698b5..dd09306ed 100644 --- a/core/commands/object.go +++ b/core/commands/object.go @@ -71,14 +71,20 @@ output is the raw data of the object. Arguments: []cmds.Argument{ cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } key := req.Arguments()[0] - return objectData(n, key) + output, err := objectData(n, key) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) }, } @@ -95,14 +101,20 @@ multihash. Arguments: []cmds.Argument{ cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } key := req.Arguments()[0] - return objectLinks(n, key) + output, err := objectLinks(n, key) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { @@ -137,17 +149,19 @@ This command outputs data in the following encodings: Arguments: []cmds.Argument{ cmds.StringArg("key", true, false, "Key of the object to retrieve (in base58-encoded multihash format)").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } key := req.Arguments()[0] object, err := objectGet(n, key) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } node := &Node{ @@ -163,7 +177,7 @@ This command outputs data in the following encodings: } } - return node, nil + res.SetOutput(node) }, Type: Node{}, Marshalers: cmds.MarshalerMap{ @@ -201,25 +215,28 @@ var objectStatCmd = &cmds.Command{ Arguments: []cmds.Argument{ cmds.StringArg("key", true, false, "Key of the object to retrieve (in base58-encoded multihash format)").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } key := req.Arguments()[0] object, err := objectGet(n, key) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } ns, err := object.Stat() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return ns, nil + res.SetOutput(ns) }, Type: dag.NodeStat{}, Marshalers: cmds.MarshalerMap{ @@ -263,15 +280,17 @@ Data should be in the format specified by . cmds.FileArg("data", true, false, "Data to be stored as a DAG object"), cmds.StringArg("encoding", true, false, "Encoding type of , either \"protobuf\" or \"json\""), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } input, err := req.Files().NextFile() if err != nil && err != io.EOF { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } encoding := req.Arguments()[0] @@ -282,10 +301,11 @@ Data should be in the format specified by . if err == ErrUnknownObjectEnc { errType = cmds.ErrClient } - return nil, cmds.Error{err.Error(), errType} + res.SetError(err, errType) + return } - return output, nil + res.SetOutput(output) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { diff --git a/core/commands/pin.go b/core/commands/pin.go index bd6c5589b..9b27f6e66 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -42,16 +42,18 @@ on disk. cmds.BoolOption("recursive", "r", "Recursively pin the object linked to by the specified object(s)"), }, Type: PinOutput{}, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } // set recursive flag recursive, found, err := req.Option("recursive").Bool() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if !found { recursive = false @@ -59,10 +61,11 @@ on disk. added, err := corerepo.Pin(n, req.Arguments(), recursive) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return &PinOutput{added}, nil + res.SetOutput(&PinOutput{added}) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { @@ -104,16 +107,18 @@ collected if needed. cmds.BoolOption("recursive", "r", "Recursively unpin the object linked to by the specified object(s)"), }, Type: PinOutput{}, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } // set recursive flag recursive, found, err := req.Option("recursive").Bool() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if !found { recursive = false // default @@ -121,10 +126,11 @@ collected if needed. removed, err := corerepo.Unpin(n, req.Arguments(), recursive) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return &PinOutput{removed}, nil + res.SetOutput(&PinOutput{removed}) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { @@ -165,15 +171,17 @@ Use --type= to specify the type of pinned keys to list. Valid values are: Options: []cmds.Option{ cmds.StringOption("type", "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\". Defaults to \"direct\""), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } typeStr, found, err := req.Option("type").String() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if !found { typeStr = "direct" @@ -182,7 +190,8 @@ Use --type= to specify the type of pinned keys to list. Valid values are: switch typeStr { case "all", "direct", "indirect", "recursive": default: - return nil, cmds.ClientError("Invalid type '" + typeStr + "', must be one of {direct, indirect, recursive, all}") + err = fmt.Errorf("Invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr) + res.SetError(err, cmds.ErrClient) } keys := make([]u.Key, 0) @@ -196,7 +205,7 @@ Use --type= to specify the type of pinned keys to list. Valid values are: keys = append(keys, n.Pinning.RecursiveKeys()...) } - return &KeyList{Keys: keys}, nil + res.SetOutput(&KeyList{Keys: keys}) }, Type: KeyList{}, Marshalers: cmds.MarshalerMap{ diff --git a/core/commands/ping.go b/core/commands/ping.go index d14beb8f0..73636db92 100644 --- a/core/commands/ping.go +++ b/core/commands/ping.go @@ -74,21 +74,24 @@ trip latency information. }, nil }, }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { ctx := req.Context().Context n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } // Must be online! if !n.OnlineMode() { - return nil, errNotOnline + res.SetError(errNotOnline, cmds.ErrClient) + return } addr, peerID, err := ParsePeerParam(req.Arguments()[0]) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if addr != nil { @@ -99,14 +102,15 @@ trip latency information. numPings := 10 val, found, err := req.Option("count").Int() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if found { numPings = val } outChan := pingPeer(ctx, n, peerID, numPings) - return outChan, nil + res.SetOutput(outChan) }, Type: PingResult{}, } diff --git a/core/commands/publish.go b/core/commands/publish.go index 4304ef1e8..9b4d4014f 100644 --- a/core/commands/publish.go +++ b/core/commands/publish.go @@ -46,21 +46,23 @@ Publish a to another public key: cmds.StringArg("name", false, false, "The IPNS name to publish to. Defaults to your node's peerID"), cmds.StringArg("ipfs-path", true, false, "IPFS path of the obejct to be published at ").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { log.Debug("Begin Publish") n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } args := req.Arguments() if n.PeerHost == nil { - return nil, errNotOnline + res.SetError(errNotOnline, cmds.ErrClient) } if n.Identity == "" { - return nil, errors.New("Identity not loaded!") + res.SetError(errors.New("Identity not loaded!"), cmds.ErrNormal) + return } // name := "" @@ -70,14 +72,19 @@ Publish a to another public key: case 2: // name = args[0] ref = args[1] - return nil, errors.New("keychains not yet implemented") + res.SetError(errors.New("keychains not yet implemented"), cmds.ErrNormal) case 1: // name = n.Identity.ID.String() ref = args[0] } // TODO n.Keychain.Get(name).PrivKey - return publish(n, n.PrivateKey, ref) + output, err := publish(n, n.PrivateKey, ref) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { diff --git a/core/commands/refs.go b/core/commands/refs.go index 3aa38d2dd..36f5db026 100644 --- a/core/commands/refs.go +++ b/core/commands/refs.go @@ -53,36 +53,42 @@ Note: list all refs recursively with -r. cmds.BoolOption("unique", "u", "Omit duplicate refs from output"), cmds.BoolOption("recursive", "r", "Recursively list links of child nodes"), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { ctx := req.Context().Context n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } unique, _, err := req.Option("unique").Bool() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } recursive, _, err := req.Option("recursive").Bool() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } edges, _, err := req.Option("edges").Bool() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } format, _, err := req.Option("format").String() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } objs, err := objectsForPaths(n, req.Arguments()) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } piper, pipew := io.Pipe() @@ -110,7 +116,7 @@ Note: list all refs recursively with -r. } }() - return eptr, nil + res.SetOutput(eptr) }, } @@ -122,17 +128,19 @@ Displays the hashes of all local objects. `, }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { ctx := req.Context().Context n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } // todo: make async allKeys, err := n.Blockstore.AllKeysChan(ctx, 0, 0) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } piper, pipew := io.Pipe() @@ -151,7 +159,7 @@ Displays the hashes of all local objects. } }() - return eptr, nil + res.SetOutput(eptr) }, } diff --git a/core/commands/repo.go b/core/commands/repo.go index 1d9a43b77..eae7a77ec 100644 --- a/core/commands/repo.go +++ b/core/commands/repo.go @@ -36,26 +36,28 @@ order to reclaim hard disk space. Options: []cmds.Option{ cmds.BoolOption("quiet", "q", "Write minimal output"), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } gcOutChan, err := corerepo.GarbageCollectBlockstore(n, req.Context().Context) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } outChan := make(chan interface{}) + res.SetOutput((<-chan interface{})(outChan)) + go func() { defer close(outChan) for k := range gcOutChan { outChan <- k } }() - - return outChan, nil }, Type: corerepo.KeyRemoved{}, Marshalers: cmds.MarshalerMap{ diff --git a/core/commands/resolve.go b/core/commands/resolve.go index d76cf8f8f..cb4703e11 100644 --- a/core/commands/resolve.go +++ b/core/commands/resolve.go @@ -40,22 +40,25 @@ Resolve te value of another name: Arguments: []cmds.Argument{ cmds.StringArg("name", false, false, "The IPNS name to resolve. Defaults to your node's peerID.").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } var name string if n.PeerHost == nil { - return nil, errNotOnline + res.SetError(errNotOnline, cmds.ErrClient) + return } if len(req.Arguments()) == 0 { if n.Identity == "" { - return nil, errors.New("Identity not loaded!") + res.SetError(errors.New("Identity not loaded!"), cmds.ErrNormal) + return } name = n.Identity.Pretty() @@ -65,12 +68,13 @@ Resolve te value of another name: output, err := n.Namesys.Resolve(name) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } // TODO: better errors (in the case of not finding the name, we get "failed to find any peer in table") - return output, nil + res.SetOutput(output) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { diff --git a/core/commands/swarm.go b/core/commands/swarm.go index 4fc53022d..1e97a30f9 100644 --- a/core/commands/swarm.go +++ b/core/commands/swarm.go @@ -45,16 +45,18 @@ var swarmPeersCmd = &cmds.Command{ ipfs swarm peers lists the set of peers this node is connected to. `, }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { log.Debug("ipfs swarm peers") n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } if n.PeerHost == nil { - return nil, errNotOnline + res.SetError(errNotOnline, cmds.ErrClient) + return } conns := n.PeerHost.Network().Conns() @@ -66,7 +68,7 @@ ipfs swarm peers lists the set of peers this node is connected to. } sort.Sort(sort.StringSlice(addrs)) - return &stringList{addrs}, nil + res.SetOutput(&stringList{addrs}) }, Marshalers: cmds.MarshalerMap{ cmds.Text: stringListMarshaler, @@ -87,24 +89,27 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/QmaCpDMGvV2BGHeYERUEnRQAwe3N8Szb Arguments: []cmds.Argument{ cmds.StringArg("address", true, true, "address of peer to connect to").EnableStdin(), }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { ctx := context.TODO() log.Debug("ipfs swarm connect") n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } addrs := req.Arguments() if n.PeerHost == nil { - return nil, errNotOnline + res.SetError(errNotOnline, cmds.ErrClient) + return } peers, err := peersWithAddresses(n.Peerstore, addrs) if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } output := make([]string, len(peers)) @@ -119,7 +124,7 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/QmaCpDMGvV2BGHeYERUEnRQAwe3N8Szb } } - return &stringList{output}, nil + res.SetOutput(&stringList{output}) }, Marshalers: cmds.MarshalerMap{ cmds.Text: stringListMarshaler, diff --git a/core/commands/update.go b/core/commands/update.go index bc4fd40c7..715ac6354 100644 --- a/core/commands/update.go +++ b/core/commands/update.go @@ -22,12 +22,19 @@ var UpdateCmd = &cmds.Command{ ShortDescription: "ipfs update is a utility command used to check for updates and apply them.", }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return updateApply(n) + + output, err := updateApply(n) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) }, Type: UpdateOutput{}, Subcommands: map[string]*cmds.Command{ @@ -55,12 +62,19 @@ var UpdateCheckCmd = &cmds.Command{ ShortDescription: "'ipfs update check' checks if any updates are available for IPFS.\nNothing will be downloaded or installed.", }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return updateCheck(n) + + output, err := updateCheck(n) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) }, Type: UpdateOutput{}, Marshalers: cmds.MarshalerMap{ @@ -84,12 +98,19 @@ var UpdateLogCmd = &cmds.Command{ ShortDescription: "This command is not yet implemented.", }, - Run: func(req cmds.Request) (interface{}, error) { + Run: func(req cmds.Request, res cmds.Response) { n, err := req.Context().GetNode() if err != nil { - return nil, err + res.SetError(err, cmds.ErrNormal) + return } - return updateLog(n) + + output, err := updateLog(n) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + res.SetOutput(output) }, } diff --git a/core/commands/version.go b/core/commands/version.go index 9ed89d315..d142c4ea2 100644 --- a/core/commands/version.go +++ b/core/commands/version.go @@ -22,10 +22,10 @@ var VersionCmd = &cmds.Command{ Options: []cmds.Option{ cmds.BoolOption("number", "n", "Only show the version number"), }, - Run: func(req cmds.Request) (interface{}, error) { - return &VersionOutput{ + Run: func(req cmds.Request, res cmds.Response) { + res.SetOutput(&VersionOutput{ Version: config.CurrentVersionNumber, - }, nil + }) }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) {