Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

commands/refs: use new cmds #5679

Merged
merged 4 commits into from
Nov 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions core/commands/filestore.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,18 +203,8 @@ var dupsFileStore = &cmds.Command{

return nil
},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *RefWrapper) error {
if out.Err != "" {
return fmt.Errorf(out.Err)
}

fmt.Fprintln(w, out.Ref)

return nil
}),
},
Type: RefWrapper{},
Encoders: refsEncoderMap,
Type: RefWrapper{},
}

func getFilestore(env cmds.Environment) (*core.IpfsNode, *filestore.Filestore, error) {
Expand Down
188 changes: 61 additions & 127 deletions core/commands/refs.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
package commands

import (
"bytes"
"context"
"errors"
"fmt"
"io"
"strings"

cmds "github.com/ipfs/go-ipfs/commands"
"github.com/ipfs/go-ipfs/core"
e "github.com/ipfs/go-ipfs/core/commands/e"
core "github.com/ipfs/go-ipfs/core"
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv"

cid "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid"
path "gx/ipfs/QmRG3XuGwT7GYuAqgWDJBKTzdaHMwAnc1x7J2KHEXNHxzG/go-path"
cmds "gx/ipfs/Qma6uuSyjkecGhMFFLfzyJDPyoDtNJSHJNweDccZhaWkgU/go-ipfs-cmds"
ipld "gx/ipfs/QmcKKBwfz6FyQdHR2jsXrrF6XeSBXYL86anmWNewpFpoF5/go-ipld-format"
cmdkit "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
)

var refsEncoderMap = cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *RefWrapper) error {
if out.Err != "" {
return fmt.Errorf(out.Err)
}
fmt.Fprintln(w, out.Ref)

return nil
}),
}

// KeyList is a general type for outputting lists of keys
type KeyList struct {
Keys []cid.Cid
Expand All @@ -30,25 +41,7 @@ const (
refsMaxDepthOptionName = "max-depth"
)

// KeyListTextMarshaler outputs a KeyList as plaintext, one key per line
func KeyListTextMarshaler(res cmds.Response) (io.Reader, error) {
out, err := unwrapOutput(res.Output())
if err != nil {
return nil, err
}

output, ok := out.(*KeyList)
if !ok {
return nil, e.TypeErr(output, out)
}

buf := new(bytes.Buffer)
for _, key := range output.Keys {
buf.WriteString(key.String() + "\n")
}
return buf, nil
}

// RefsCmd is the `ipfs refs` command
var RefsCmd = &cmds.Command{
Helptext: cmdkit.HelpText{
Tagline: "List links (references) from an object.",
Expand All @@ -74,91 +67,62 @@ NOTE: List all references recursively by using the flag '-r'.
cmdkit.BoolOption(refsRecursiveOptionName, "r", "Recursively list links of child nodes."),
cmdkit.IntOption(refsMaxDepthOptionName, "Only for recursive refs, limits fetch and listing to the given depth").WithDefault(-1),
},
Run: func(req cmds.Request, res cmds.Response) {
ctx := req.Context()
n, err := req.InvocContext().GetNode()
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
err := req.ParseBodyArgs()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move this down...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meh? Honestly, if we're going to do this up-front anyways, we might as well finish parsing the request as early as possible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can change this later if you'd like.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really have a strong preference but we should at least try and be consistent about when we do this.

In any case fixing it now is a low priority.

if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
return err
}

unique, _, err := req.Option(refsUniqueOptionName).Bool()
ctx := req.Context
n, err := cmdenv.GetNode(env)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
return err
}

recursive, _, err := req.Option(refsRecursiveOptionName).Bool()
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
}

maxDepth, _, err := req.Option(refsMaxDepthOptionName).Int()
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
}
unique, _ := req.Options[refsUniqueOptionName].(bool)
recursive, _ := req.Options[refsRecursiveOptionName].(bool)
maxDepth, _ := req.Options[refsMaxDepthOptionName].(int)
edges, _ := req.Options[refsEdgesOptionName].(bool)
format, _ := req.Options[refsFormatOptionName].(string)

if !recursive {
maxDepth = 1 // write only direct refs
}

format, _, err := req.Option(refsFormatOptionName).String()
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
}

edges, _, err := req.Option(refsEdgesOptionName).Bool()
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
}
if edges {
if format != "<dst>" {
res.SetError(errors.New("using format argument with edges is not allowed"),
cmdkit.ErrClient)
return
return errors.New("using format argument with edges is not allowed")
}

format = "<src> -> <dst>"
}

objs, err := objectsForPaths(ctx, n, req.Arguments())
objs, err := objectsForPaths(ctx, n, req.Arguments)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
return err
}

out := make(chan interface{})
res.SetOutput((<-chan interface{})(out))

go func() {
defer close(out)

rw := RefWriter{
out: out,
DAG: n.DAG,
Ctx: ctx,
Unique: unique,
PrintFmt: format,
MaxDepth: maxDepth,
}
rw := RefWriter{
res: res,
DAG: n.DAG,
Ctx: ctx,
Unique: unique,
PrintFmt: format,
MaxDepth: maxDepth,
}

for _, o := range objs {
if _, err := rw.WriteRefs(o); err != nil {
select {
case out <- &RefWrapper{Err: err.Error()}:
case <-ctx.Done():
}
return
for _, o := range objs {
if _, err := rw.WriteRefs(o); err != nil {
if err := res.Emit(&RefWrapper{Err: err.Error()}); err != nil {
return err
}
}
}()
}

return nil
},
Marshalers: refsMarshallerMap,
Type: RefWrapper{},
Encoders: refsEncoderMap,
Type: RefWrapper{},
}

var RefsLocalCmd = &cmds.Command{
Expand All @@ -169,58 +133,30 @@ Displays the hashes of all local objects.
`,
},

Run: func(req cmds.Request, res cmds.Response) {
ctx := req.Context()
n, err := req.InvocContext().GetNode()
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
ctx := req.Context
n, err := cmdenv.GetNode(env)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
return err
}

// todo: make async
allKeys, err := n.Blockstore.AllKeysChan(ctx)
if err != nil {
res.SetError(err, cmdkit.ErrNormal)
return
return err
}

out := make(chan interface{})
res.SetOutput((<-chan interface{})(out))

go func() {
defer close(out)

for k := range allKeys {
select {
case out <- &RefWrapper{Ref: k.String()}:
case <-req.Context().Done():
return
}
for k := range allKeys {
err := res.Emit(&RefWrapper{Ref: k.String()})
if err != nil {
return err
}
}()
},
Marshalers: refsMarshallerMap,
Type: RefWrapper{},
}

var refsMarshallerMap = cmds.MarshalerMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) {
v, err := unwrapOutput(res.Output())
if err != nil {
return nil, err
}

obj, ok := v.(*RefWrapper)
if !ok {
return nil, e.TypeErr(obj, v)
}

if obj.Err != "" {
return nil, errors.New(obj.Err)
}

return strings.NewReader(obj.Ref + "\n"), nil
return nil
},
Encoders: refsEncoderMap,
Type: RefWrapper{},
}

func objectsForPaths(ctx context.Context, n *core.IpfsNode, paths []string) ([]ipld.Node, error) {
Expand All @@ -246,7 +182,7 @@ type RefWrapper struct {
}

type RefWriter struct {
out chan interface{}
res cmds.ResponseEmitter
DAG ipld.DAGService
Ctx context.Context

Expand All @@ -260,7 +196,6 @@ type RefWriter struct {
// WriteRefs writes refs of the given object to the underlying writer.
func (rw *RefWriter) WriteRefs(n ipld.Node) (int, error) {
return rw.writeRefsRecursive(n, 0)

}

func (rw *RefWriter) writeRefsRecursive(n ipld.Node, depth int) (int, error) {
Expand Down Expand Up @@ -394,6 +329,5 @@ func (rw *RefWriter) WriteEdge(from, to cid.Cid, linkname string) error {
s += to.String()
}

rw.out <- &RefWrapper{Ref: s}
return nil
return rw.res.Emit(&RefWrapper{Ref: s})
}
9 changes: 5 additions & 4 deletions core/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ var rootSubcommands = map[string]*cmds.Command{
"pin": lgc.NewCommand(PinCmd),
"ping": PingCmd,
"p2p": P2PCmd,
"refs": lgc.NewCommand(RefsCmd),
"refs": RefsCmd,
"resolve": ResolveCmd,
"swarm": SwarmCmd,
"tar": TarCmd,
Expand All @@ -155,7 +155,8 @@ var RootRO = &cmds.Command{}

var CommandsDaemonROCmd = CommandsCmd(RootRO)

var RefsROCmd = &oldcmds.Command{}
// RefsROCmd is `ipfs refs` command
var RefsROCmd = &cmds.Command{}

var rootROSubcommands = map[string]*cmds.Command{
"commands": CommandsDaemonROCmd,
Expand Down Expand Up @@ -198,12 +199,12 @@ func init() {

// sanitize readonly refs command
*RefsROCmd = *RefsCmd
RefsROCmd.Subcommands = map[string]*oldcmds.Command{}
RefsROCmd.Subcommands = map[string]*cmds.Command{}

// this was in the big map definition above before,
// but if we leave it there lgc.NewCommand will be executed
// before the value is updated (:/sanitize readonly refs command/)
rootROSubcommands["refs"] = lgc.NewCommand(RefsROCmd)
rootROSubcommands["refs"] = RefsROCmd

Root.Subcommands = rootSubcommands

Expand Down