diff --git a/commands/response.go b/commands/response.go index a720a8214542d5a6a42cd41f6be95bf700343e0b..657dd0403e2a647d80f708e89900016337b77cb7 100644 --- a/commands/response.go +++ b/commands/response.go @@ -15,8 +15,9 @@ type ErrorType uint // ErrorTypes convey what category of error ocurred const ( - ErrNormal ErrorType = iota // general errors - ErrClient // error was caused by the client, (e.g. invalid CLI usage) + ErrNormal ErrorType = iota // general errors + ErrClient // error was caused by the client, (e.g. invalid CLI usage) + ErrImplementation // programmer error in the server // TODO: add more types of errors for better error-specific handling ) diff --git a/core/commands/unixfs/ls.go b/core/commands/unixfs/ls.go index 58ad2f811efb4eb8e4292e2b700ff539914fa839..9d9cdbdbb553cfe5566253635022cabc0eac5eef 100644 --- a/core/commands/unixfs/ls.go +++ b/core/commands/unixfs/ls.go @@ -59,40 +59,66 @@ directories, the child size is the IPFS link size. output := make([]*LsObject, len(paths)) for i, fpath := range paths { - dagnode, err := core.Resolve(req.Context().Context, node, path.Path(fpath)) + ctx := req.Context().Context + merkleNode, err := core.Resolve(ctx, node, path.Path(fpath)) if err != nil { res.SetError(err, cmds.ErrNormal) return } - output[i] = &LsObject{ - Argument: fpath, - Links: make([]LsLink, len(dagnode.Links)), + unixFSNode, err := unixfs.FromBytes(merkleNode.Data) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return } - for j, link := range dagnode.Links { - ctx, cancel := context.WithTimeout(context.TODO(), time.Minute) - defer cancel() - link.Node, err = link.GetNode(ctx, node.DAG) - if err != nil { - res.SetError(err, cmds.ErrNormal) - return - } - d, err := unixfs.FromBytes(link.Node.Data) + + output[i] = &LsObject{} + + t := unixFSNode.GetType() + switch t { + default: + res.SetError(fmt.Errorf("unrecognized type: %s", t), cmds.ErrImplementation) + return + case unixfspb.Data_File: + key, err := merkleNode.Key() if err != nil { res.SetError(err, cmds.ErrNormal) return } - lsLink := LsLink{ - Name: link.Name, - Hash: link.Hash.B58String(), - Type: d.GetType(), + output[i].Links = []LsLink{LsLink{ + Name: fpath, + Hash: key.String(), + Type: t, + Size: unixFSNode.GetFilesize(), + }} + case unixfspb.Data_Directory: + output[i].Argument = fpath + output[i].Links = make([]LsLink, len(merkleNode.Links)) + for j, link := range merkleNode.Links { + getCtx, cancel := context.WithTimeout(context.TODO(), time.Minute) + defer cancel() + link.Node, err = link.GetNode(getCtx, node.DAG) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + d, err := unixfs.FromBytes(link.Node.Data) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + lsLink := LsLink{ + Name: link.Name, + Hash: link.Hash.B58String(), + Type: d.GetType(), + } + if lsLink.Type == unixfspb.Data_File { + lsLink.Size = d.GetFilesize() + } else { + lsLink.Size = link.Size + } + output[i].Links[j] = lsLink } - if lsLink.Type == unixfspb.Data_File { - lsLink.Size = d.GetFilesize() - } else { - lsLink.Size = link.Size - } - output[i].Links[j] = lsLink } } @@ -104,16 +130,23 @@ directories, the child size is the IPFS link size. output := res.Output().(*LsOutput) buf := new(bytes.Buffer) w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0) - for _, object := range output.Objects { - if len(output.Objects) > 1 { + lastObjectDirHeader := false + for i, object := range output.Objects { + if len(output.Objects) > 1 && object.Argument != "" { + if i > 0 { + fmt.Fprintln(w) + } fmt.Fprintf(w, "%s:\n", object.Argument) + lastObjectDirHeader = true + } else { + if lastObjectDirHeader { + fmt.Fprintln(w) + } + lastObjectDirHeader = false } for _, link := range object.Links { fmt.Fprintf(w, "%s\n", link.Name) } - if len(output.Objects) > 1 { - fmt.Fprintln(w) - } } w.Flush() diff --git a/test/sharness/t0200-unixfs-ls.sh b/test/sharness/t0200-unixfs-ls.sh index f5dc20d305458edc0a667c8733fb22ae7be58b63..4d980e44e468d325ea06c766451d5cf95446e077 100755 --- a/test/sharness/t0200-unixfs-ls.sh +++ b/test/sharness/t0200-unixfs-ls.sh @@ -57,10 +57,21 @@ test_ls_cmd() { QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss: 128 a - EOF test_cmp expected_ls actual_ls ' + + test_expect_success "'ipfs unixfs ls <file hashes>' succeeds" ' + ipfs unixfs ls /ipfs/QmR3jhV4XpxxPjPT3Y8vNnWvWNvakdcT3H6vqpRBsX1MLy/1024 QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe >actual_ls_file + ' + + test_expect_success "'ipfs unixfs ls <file hashes>' output looks good" ' + cat <<-\EOF >expected_ls_file && + /ipfs/QmR3jhV4XpxxPjPT3Y8vNnWvWNvakdcT3H6vqpRBsX1MLy/1024 + QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe + EOF + test_cmp expected_ls_file actual_ls_file + ' }