From dc9456f56d45f613095a6aea6a769a9aed8337f2 Mon Sep 17 00:00:00 2001 From: Overbool Date: Thu, 20 Sep 2018 23:57:59 +0800 Subject: [PATCH 1/3] feat(command): merge file ls and ls License: MIT Signed-off-by: Overbool --- core/commands/ls.go | 122 +++++++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 40 deletions(-) diff --git a/core/commands/ls.go b/core/commands/ls.go index 5981d036022..73c4e3a9abd 100644 --- a/core/commands/ls.go +++ b/core/commands/ls.go @@ -29,6 +29,8 @@ type LsLink struct { type LsObject struct { Hash string + Size uint64 + Type string Links []LsLink } @@ -116,60 +118,94 @@ The JSON output contains type information. ro := merkledag.NewReadOnlyDagService(ng) for i, dagnode := range dagnodes { - dir, err := uio.NewDirectoryFromNode(ro, dagnode) - if err != nil && err != uio.ErrNotADir { - res.SetError(fmt.Errorf("the data in %s (at %q) is not a UnixFS directory: %s", dagnode.Cid(), paths[i], err), cmdkit.ErrNormal) + dagp, ok := dagnode.(*merkledag.ProtoNode) + if !ok { + res.SetError(merkledag.ErrNotProtobuf, cmdkit.ErrNormal) return } - var links []*ipld.Link - if dir == nil { - links = dagnode.Links() - } else { - links, err = dir.Links(req.Context()) - if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return - } - } - - output[i] = LsObject{ - Hash: paths[i], - Links: make([]LsLink, len(links)), + fsn, err := unixfs.FSNodeFromBytes(dagp.Data()) + if err != nil { + res.SetError(err, cmdkit.ErrNormal) + return } - for j, link := range links { - t := unixfspb.Data_DataType(-1) - - switch link.Cid.Type() { - case cid.Raw: - // No need to check with raw leaves - t = unixfs.TFile - case cid.DagProtobuf: - linkNode, err := link.GetNode(req.Context(), dserv) - if err == ipld.ErrNotFound && !resolve { - // not an error - linkNode = nil - } else if err != nil { + switch fsn.Type() { + case unixfs.TSymlink: + res.SetError(fmt.Errorf("cannot list symlinks yet"), cmdkit.ErrNormal) + return + case unixfs.THAMTShard: + res.SetError(fmt.Errorf("cannot list large directories yet"), cmdkit.ErrNormal) + return + case unixfs.TFile: + output[i] = LsObject{ + Hash: paths[i], + Size: fsn.FileSize(), + } + case unixfs.TDirectory: + dir, err := uio.NewDirectoryFromNode(ro, dagnode) + if err != nil && err != uio.ErrNotADir { + res.SetError(fmt.Errorf("the data in %s (at %q) is not a UnixFS directory: %s", dagnode.Cid(), paths[i], err), cmdkit.ErrNormal) + return + } + var links []*ipld.Link + if dir == nil { + links = dagnode.Links() + } else { + links, err = dir.Links(req.Context()) + if err != nil { res.SetError(err, cmdkit.ErrNormal) return } + } + + output[i] = LsObject{ + Hash: paths[i], + Type: fsn.Type().String(), + Links: make([]LsLink, len(links)), + } - if pn, ok := linkNode.(*merkledag.ProtoNode); ok { - d, err := unixfs.FSNodeFromBytes(pn.Data()) - if err != nil { + for j, link := range links { + t := unixfspb.Data_DataType(-1) + size := uint64(0) + switch link.Cid.Type() { + case cid.Raw: + // No need to check with raw leaves + t = unixfs.TFile + case cid.DagProtobuf: + linkNode, err := link.GetNode(req.Context(), dserv) + if err == ipld.ErrNotFound && !resolve { + // not an error + linkNode = nil + } else if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - t = d.Type() + + t = fsn.Type() + if pn, ok := linkNode.(*merkledag.ProtoNode); ok { + fsn, err := unixfs.FSNodeFromBytes(pn.Data()) + if err != nil { + res.SetError(err, cmdkit.ErrNormal) + return + } + if t == unixfs.TFile { + size = fsn.FileSize() + } else { + size = link.Size + } + } + } + output[i].Links[j] = LsLink{ + Name: link.Name, + Hash: link.Cid.String(), + Size: size, + Type: t, } } - output[i].Links[j] = LsLink{ - Name: link.Name, - Hash: link.Cid.String(), - Size: link.Size, - Type: t, - } + default: + res.SetError(fmt.Errorf("unrecognized type: %s", fsn.Type()), cmdkit.ErrImplementation) + return } } @@ -198,6 +234,12 @@ The JSON output contains type information. if headers { fmt.Fprintln(w, "Hash\tSize\tName") } + + // file object + if object.Hash != "" && object.Links == nil { + fmt.Fprintf(w, "%s\t%v\t\n", object.Hash, object.Size) + } + for _, link := range object.Links { if link.Type == unixfs.TDirectory { link.Name += "/" From 273343d20124d6d01d2a172fc38598908d6a2508 Mon Sep 17 00:00:00 2001 From: Overbool Date: Wed, 10 Oct 2018 20:20:38 +0800 Subject: [PATCH 2/3] test(ls): modify ipfs ls test License: MIT Signed-off-by: Overbool --- core/commands/ls.go | 3 ++- test/sharness/t0045-ls.sh | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/core/commands/ls.go b/core/commands/ls.go index 73c4e3a9abd..4099f052f43 100644 --- a/core/commands/ls.go +++ b/core/commands/ls.go @@ -172,6 +172,7 @@ The JSON output contains type information. case cid.Raw: // No need to check with raw leaves t = unixfs.TFile + size = link.Size case cid.DagProtobuf: linkNode, err := link.GetNode(req.Context(), dserv) if err == ipld.ErrNotFound && !resolve { @@ -182,9 +183,9 @@ The JSON output contains type information. return } - t = fsn.Type() if pn, ok := linkNode.(*merkledag.ProtoNode); ok { fsn, err := unixfs.FSNodeFromBytes(pn.Data()) + t = fsn.Type() if err != nil { res.SetError(err, cmdkit.ErrNormal) return diff --git a/test/sharness/t0045-ls.sh b/test/sharness/t0045-ls.sh index 2cb46a7dde9..f37fa5fd356 100755 --- a/test/sharness/t0045-ls.sh +++ b/test/sharness/t0045-ls.sh @@ -47,16 +47,16 @@ EOF QmfNy183bXiRVyrhyWtq3TwHn79yHEkiAGFr18P7YNzESj: QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss 246 d1/ QmR3jhV4XpxxPjPT3Y8vNnWvWNvakdcT3H6vqpRBsX1MLy 1143 d2/ -QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH 13 f1 -QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M 13 f2 +QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH 5 f1 +QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M 5 f2 QmR3jhV4XpxxPjPT3Y8vNnWvWNvakdcT3H6vqpRBsX1MLy: -QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd 1035 1024 -QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL 14 a +QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd 1024 1024 +QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL 6 a QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss: -QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 139 128 -QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 14 a +QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 128 128 +QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 6 a EOF test_cmp expected_ls actual_ls @@ -72,18 +72,18 @@ QmfNy183bXiRVyrhyWtq3TwHn79yHEkiAGFr18P7YNzESj: Hash Size Name QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss 246 d1/ QmR3jhV4XpxxPjPT3Y8vNnWvWNvakdcT3H6vqpRBsX1MLy 1143 d2/ -QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH 13 f1 -QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M 13 f2 +QmeomffUNfmQy76CQGy9NdmqEnnHU9soCexBnGU3ezPHVH 5 f1 +QmNtocSs7MoDkJMc1RkyisCSKvLadujPsfJfSdJ3e1eA1M 5 f2 QmR3jhV4XpxxPjPT3Y8vNnWvWNvakdcT3H6vqpRBsX1MLy: Hash Size Name -QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd 1035 1024 -QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL 14 a +QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd 1024 1024 +QmaRGe7bVmVaLmxbrMiVNXqW4pRNNp3xq7hFtyRKA3mtJL 6 a QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss: Hash Size Name -QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 139 128 -QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 14 a +QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe 128 128 +QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN 6 a EOF test_cmp expected_ls_headers actual_ls_headers From c36b563353ceecf04fa942c9c9cfdaf73263f824 Mon Sep 17 00:00:00 2001 From: Overbool Date: Wed, 10 Oct 2018 20:38:48 +0800 Subject: [PATCH 3/3] fix(ls): list file License: MIT Signed-off-by: Overbool --- core/commands/ls.go | 95 +++++++++++++++++++-------------------- test/sharness/t0045-ls.sh | 4 +- 2 files changed, 49 insertions(+), 50 deletions(-) diff --git a/core/commands/ls.go b/core/commands/ls.go index 4099f052f43..425eb1301cd 100644 --- a/core/commands/ls.go +++ b/core/commands/ls.go @@ -130,6 +130,8 @@ The JSON output contains type information. return } + var links []*ipld.Link + switch fsn.Type() { case unixfs.TSymlink: res.SetError(fmt.Errorf("cannot list symlinks yet"), cmdkit.ErrNormal) @@ -138,25 +140,22 @@ The JSON output contains type information. res.SetError(fmt.Errorf("cannot list large directories yet"), cmdkit.ErrNormal) return case unixfs.TFile: + links = dagnode.Links() output[i] = LsObject{ - Hash: paths[i], - Size: fsn.FileSize(), + Hash: paths[i], + Size: fsn.FileSize(), + Links: make([]LsLink, len(links)), } case unixfs.TDirectory: dir, err := uio.NewDirectoryFromNode(ro, dagnode) - if err != nil && err != uio.ErrNotADir { + if err != nil { res.SetError(fmt.Errorf("the data in %s (at %q) is not a UnixFS directory: %s", dagnode.Cid(), paths[i], err), cmdkit.ErrNormal) return } - var links []*ipld.Link - if dir == nil { - links = dagnode.Links() - } else { - links, err = dir.Links(req.Context()) - if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return - } + links, err = dir.Links(req.Context()) + if err != nil { + res.SetError(err, cmdkit.ErrNormal) + return } output[i] = LsObject{ @@ -164,49 +163,49 @@ The JSON output contains type information. Type: fsn.Type().String(), Links: make([]LsLink, len(links)), } + default: + res.SetError(fmt.Errorf("unrecognized type: %s", fsn.Type()), cmdkit.ErrImplementation) + return + } - for j, link := range links { - t := unixfspb.Data_DataType(-1) - size := uint64(0) - switch link.Cid.Type() { - case cid.Raw: - // No need to check with raw leaves - t = unixfs.TFile - size = link.Size - case cid.DagProtobuf: - linkNode, err := link.GetNode(req.Context(), dserv) - if err == ipld.ErrNotFound && !resolve { - // not an error - linkNode = nil - } else if err != nil { + for j, link := range links { + t := unixfspb.Data_DataType(-1) + size := uint64(0) + switch link.Cid.Type() { + case cid.Raw: + // No need to check with raw leaves + t = unixfs.TFile + size = link.Size + case cid.DagProtobuf: + linkNode, err := link.GetNode(req.Context(), dserv) + if err == ipld.ErrNotFound && !resolve { + // not an error + linkNode = nil + } else if err != nil { + res.SetError(err, cmdkit.ErrNormal) + return + } + + if pn, ok := linkNode.(*merkledag.ProtoNode); ok { + fsn, err := unixfs.FSNodeFromBytes(pn.Data()) + t = fsn.Type() + if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - - if pn, ok := linkNode.(*merkledag.ProtoNode); ok { - fsn, err := unixfs.FSNodeFromBytes(pn.Data()) - t = fsn.Type() - if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return - } - if t == unixfs.TFile { - size = fsn.FileSize() - } else { - size = link.Size - } + if t == unixfs.TFile { + size = fsn.FileSize() + } else { + size = link.Size } } - output[i].Links[j] = LsLink{ - Name: link.Name, - Hash: link.Cid.String(), - Size: size, - Type: t, - } } - default: - res.SetError(fmt.Errorf("unrecognized type: %s", fsn.Type()), cmdkit.ErrImplementation) - return + output[i].Links[j] = LsLink{ + Name: link.Name, + Hash: link.Cid.String(), + Size: size, + Type: t, + } } } diff --git a/test/sharness/t0045-ls.sh b/test/sharness/t0045-ls.sh index f37fa5fd356..1778ab0c75f 100755 --- a/test/sharness/t0045-ls.sh +++ b/test/sharness/t0045-ls.sh @@ -105,8 +105,8 @@ test_ls_object() { test_expect_success "ipfs add medium size file then 'ipfs ls' works as expected" ' random 500000 2 > somefile && HASH=$(ipfs add somefile -q) && - echo "QmPrM8S5T7Q3M8DQvQMS7m41m3Aq4jBjzAzvky5fH3xfr4 262158 " > ls-expect && - echo "QmdaAntAzQqqVMo4B8V69nkQd5d918YjHXUe2oF6hr72ri 237870 " >> ls-expect && + echo "QmPrM8S5T7Q3M8DQvQMS7m41m3Aq4jBjzAzvky5fH3xfr4 262144 " > ls-expect && + echo "QmdaAntAzQqqVMo4B8V69nkQd5d918YjHXUe2oF6hr72ri 237856 " >> ls-expect && ipfs ls $HASH > ls-actual && test_cmp ls-actual ls-expect '