github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/core/commands2/refs.go (about)

     1  package commands
     2  
     3  import (
     4  	"fmt"
     5  
     6  	mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
     7  	cmds "github.com/jbenet/go-ipfs/commands"
     8  	"github.com/jbenet/go-ipfs/core"
     9  	"github.com/jbenet/go-ipfs/core/commands2/internal"
    10  	dag "github.com/jbenet/go-ipfs/merkledag"
    11  	u "github.com/jbenet/go-ipfs/util"
    12  )
    13  
    14  type RefsOutput struct {
    15  	Refs []string
    16  }
    17  
    18  var refsCmd = &cmds.Command{
    19  	Description: "Lists link hashes from an object",
    20  	Help: `Retrieves the object named by <ipfs-path> and displays the link
    21  hashes it contains, with the following format:
    22  
    23    <link base58 hash>
    24  
    25  Note: list all refs recursively with -r.`,
    26  
    27  	Arguments: []cmds.Argument{
    28  		cmds.StringArg("ipfs-path", true, true, "Path to the object(s) to list refs from"),
    29  	},
    30  	Options: []cmds.Option{
    31  		cmds.BoolOption("unique", "u", "Omit duplicate refs from output"),
    32  		cmds.BoolOption("recursive", "r", "Recursively list links of child nodes"),
    33  	},
    34  	Run: func(req cmds.Request) (interface{}, error) {
    35  		n := req.Context().Node
    36  
    37  		unique, _ := req.Option("unique").Bool()
    38  		recursive, _ := req.Option("recursive").Bool()
    39  
    40  		paths, err := internal.CastToStrings(req.Arguments())
    41  		if err != nil {
    42  			return nil, err
    43  		}
    44  
    45  		return getRefs(n, paths, unique, recursive)
    46  	},
    47  	Type: &RefsOutput{},
    48  	Marshallers: map[cmds.EncodingType]cmds.Marshaller{
    49  		cmds.Text: func(res cmds.Response) ([]byte, error) {
    50  			output := res.Output().(*RefsOutput)
    51  			s := ""
    52  			for _, ref := range output.Refs {
    53  				s += fmt.Sprintln(ref)
    54  			}
    55  			return []byte(s), nil
    56  		},
    57  	},
    58  }
    59  
    60  func getRefs(n *core.IpfsNode, paths []string, unique, recursive bool) (*RefsOutput, error) {
    61  	var refsSeen map[u.Key]bool
    62  	if unique {
    63  		refsSeen = make(map[u.Key]bool)
    64  	}
    65  
    66  	refs := make([]string, 0)
    67  
    68  	for _, path := range paths {
    69  		object, err := n.Resolver.ResolvePath(path)
    70  		if err != nil {
    71  			return nil, err
    72  		}
    73  
    74  		refs, err = addRefs(n, object, refs, refsSeen, recursive)
    75  		if err != nil {
    76  			return nil, err
    77  		}
    78  	}
    79  
    80  	return &RefsOutput{refs}, nil
    81  }
    82  
    83  func addRefs(n *core.IpfsNode, object *dag.Node, refs []string, refsSeen map[u.Key]bool, recursive bool) ([]string, error) {
    84  	for _, link := range object.Links {
    85  		var found bool
    86  		found, refs = addRef(link.Hash, refs, refsSeen)
    87  
    88  		if recursive && !found {
    89  			child, err := n.DAG.Get(u.Key(link.Hash))
    90  			if err != nil {
    91  				return nil, fmt.Errorf("cannot retrieve %s (%s)", link.Hash.B58String(), err)
    92  			}
    93  
    94  			refs, err = addRefs(n, child, refs, refsSeen, recursive)
    95  			if err != nil {
    96  				return nil, err
    97  			}
    98  		}
    99  	}
   100  
   101  	return refs, nil
   102  }
   103  
   104  func addRef(h mh.Multihash, refs []string, refsSeen map[u.Key]bool) (bool, []string) {
   105  	if refsSeen != nil {
   106  		_, found := refsSeen[u.Key(h)]
   107  		if found {
   108  			return true, refs
   109  		}
   110  		refsSeen[u.Key(h)] = true
   111  	}
   112  
   113  	refs = append(refs, h.B58String())
   114  	return false, refs
   115  }