Skip to content

Commit bdefbbb

Browse files
committed
core/commands/unixfs/ls: Don't recurse into chunked files
Folks operating at the Unix-filesystem level shouldn't care about that level of Merkle-DAG detail. Before this commit we had: $ ipfs unixfs ls /ipfs/QmSRCHG21Sbqm3EJG9aEBo4vS7Fqu86pAjqf99MyCdNxZ4/busybox QmW1HetBAhJPQgLMpYXyRb8JV4AU8d8WFvK9wkiNc4ki31 File 262144 QmcG1bJ3dtKdEqKv4pyzNZaNdFGb4eS4TYP3MNXyj1K4sD File 262144 QmYuAwy4tEeRkWe2BG8CAUW6amjgDQAQXJ2Efikqip2r66 File 262144 QmccDNKasKMBZ7jRGfYwUwqaQrHu2GMUaD9pdYcAVjzfKV File 262144 QmYHZJzWo4UTTtsbFJU6Ls79tp8t1AxsRsG6siNefVCf17 File 262144 QmXWXzjBB9i9NkpUEausaWPE1UoZhMfhyjVeUhZAFoHmr6 File 262144 Qmasn9Hzj5PsMXoy7bnu7WVXMLq1jYg7uTs2eWoyVbyiE3 File 262144 QmTwygpqpUkCq68YLPuzwVVW2QWkt7StAPW6DvK3aQTL5v File 112616 And with this commit we have: $ ipfs unixfs ls /ipfs/QmSRCHG21Sbqm3EJG9aEBo4vS7Fqu86pAjqf99MyCdNxZ4/busybox QmPbjmmci73roXf9VijpyQGgRJZthiQfnEetaMRGoGYV5a File 1947624 /ipfs/QmSRCHG21Sbqm3EJG9aEBo4vS7Fqu86pAjqf99MyCdNxZ4/busybox I also reworked the argument-prefixing (object.Argument) in the output marshaller to avoid redundancies like: $ ipfs unixfs ls /ipfs/QmSRCHG21Sbqm3EJG9aEBo4vS7Fqu86pAjqf99MyCdNxZ4/busybox /ipfs/QmSRCHG21Sbqm3EJG9aEBo4vS7Fqu86pAjqf99MyCdNxZ4/busybox: QmPbjmmci73roXf9VijpyQGgRJZthiQfnEetaMRGoGYV5a File 1947624 /ipfs/QmSRCHG21Sbqm3EJG9aEBo4vS7Fqu86pAjqf99MyCdNxZ4/busybox As a side-effect of this rework, we no longer have the trialing blank line that we used to have after the final directory listing. I also dropped the minute-timeout context which landed in 'ipfs ls ...' with 0a6b880, fix for #1008 and other pinning fixes, #1010). Instead, I just pass through this command's context. The new ErrImplementation is like Python's NotImplementedError, and is mostly a way to guard against external changes that would need associated updates in this code. For example, once we see something that's neither a file nor a directory, we'll have to update the switch statement to handle those objects. License: MIT Signed-off-by: W. Trevor King <[email protected]>
1 parent d0ce146 commit bdefbbb

File tree

3 files changed

+74
-35
lines changed

3 files changed

+74
-35
lines changed

commands/response.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ type ErrorType uint
1515

1616
// ErrorTypes convey what category of error ocurred
1717
const (
18-
ErrNormal ErrorType = iota // general errors
19-
ErrClient // error was caused by the client, (e.g. invalid CLI usage)
18+
ErrNormal ErrorType = iota // general errors
19+
ErrClient // error was caused by the client, (e.g. invalid CLI usage)
20+
ErrImplementation // programmer error in the server
2021
// TODO: add more types of errors for better error-specific handling
2122
)
2223

core/commands/unixfs/ls.go

+59-31
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@ import (
55
"fmt"
66
"io"
77
"text/tabwriter"
8-
"time"
9-
10-
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
118

129
cmds "github.com/ipfs/go-ipfs/commands"
1310
core "github.com/ipfs/go-ipfs/core"
@@ -68,40 +65,64 @@ directories, the child size is the IPFS link size.
6865

6966
output := make([]*LsObject, len(paths))
7067
for i, fpath := range paths {
71-
dagnode, err := core.Resolve(req.Context().Context, node, path.Path(fpath))
68+
ctx := req.Context().Context
69+
merkleNode, err := core.Resolve(ctx, node, path.Path(fpath))
7270
if err != nil {
7371
res.SetError(err, cmds.ErrNormal)
7472
return
7573
}
7674

77-
output[i] = &LsObject{
78-
Argument: paths[i],
79-
Links: make([]LsLink, len(dagnode.Links)),
75+
unixFSNode, err := unixfs.FromBytes(merkleNode.Data)
76+
if err != nil {
77+
res.SetError(err, cmds.ErrNormal)
78+
return
8079
}
81-
for j, link := range dagnode.Links {
82-
ctx, cancel := context.WithTimeout(context.TODO(), time.Minute)
83-
defer cancel()
84-
link.Node, err = link.GetNode(ctx, node.DAG)
85-
if err != nil {
86-
res.SetError(err, cmds.ErrNormal)
87-
return
88-
}
89-
d, err := unixfs.FromBytes(link.Node.Data)
80+
81+
output[i] = &LsObject{}
82+
83+
t := unixFSNode.GetType()
84+
switch t {
85+
default:
86+
res.SetError(fmt.Errorf("unrecognized type: %s", t), cmds.ErrImplementation)
87+
return
88+
case unixfspb.Data_File:
89+
key, err := merkleNode.Key()
9090
if err != nil {
9191
res.SetError(err, cmds.ErrNormal)
9292
return
9393
}
94-
lsLink := LsLink{
95-
Name: link.Name,
96-
Hash: link.Hash.B58String(),
97-
Type: d.GetType(),
94+
output[i].Links = []LsLink{LsLink{
95+
Name: paths[i],
96+
Hash: key.String(),
97+
Type: t,
98+
Size: unixFSNode.GetFilesize(),
99+
}}
100+
case unixfspb.Data_Directory:
101+
output[i].Argument = paths[i]
102+
output[i].Links = make([]LsLink, len(merkleNode.Links))
103+
for j, link := range merkleNode.Links {
104+
link.Node, err = link.GetNode(ctx, node.DAG)
105+
if err != nil {
106+
res.SetError(err, cmds.ErrNormal)
107+
return
108+
}
109+
d, err := unixfs.FromBytes(link.Node.Data)
110+
if err != nil {
111+
res.SetError(err, cmds.ErrNormal)
112+
return
113+
}
114+
lsLink := LsLink{
115+
Name: link.Name,
116+
Hash: link.Hash.B58String(),
117+
Type: d.GetType(),
118+
}
119+
if lsLink.Type == unixfspb.Data_File {
120+
lsLink.Size = d.GetFilesize()
121+
} else {
122+
lsLink.Size = link.Size
123+
}
124+
output[i].Links[j] = lsLink
98125
}
99-
if lsLink.Type == unixfspb.Data_File {
100-
lsLink.Size = d.GetFilesize()
101-
} else {
102-
lsLink.Size = link.Size
103-
}
104-
output[i].Links[j] = lsLink
105126
}
106127
}
107128

@@ -114,9 +135,19 @@ directories, the child size is the IPFS link size.
114135
output := res.Output().(*LsOutput)
115136
buf := new(bytes.Buffer)
116137
w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0)
117-
for _, object := range output.Objects {
118-
if len(output.Objects) > 1 {
138+
lastObjectDirHeader := false
139+
for i, object := range output.Objects {
140+
if len(output.Objects) > 1 && object.Argument != "" {
141+
if i > 0 {
142+
fmt.Fprintln(w)
143+
}
119144
fmt.Fprintf(w, "%s:\n", object.Argument)
145+
lastObjectDirHeader = true
146+
} else {
147+
if lastObjectDirHeader {
148+
fmt.Fprintln(w)
149+
}
150+
lastObjectDirHeader = false
120151
}
121152
if headers {
122153
fmt.Fprintln(w, "Hash\tType\tSize\tName")
@@ -125,9 +156,6 @@ directories, the child size is the IPFS link size.
125156
fmt.Fprintf(w, "%s\t%s\t%v\t%s\n",
126157
link.Hash, link.Type.String(), link.Size, link.Name)
127158
}
128-
if len(output.Objects) > 1 {
129-
fmt.Fprintln(w)
130-
}
131159
}
132160
w.Flush()
133161

test/sharness/t0200-unixfs-ls.sh

+12-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ test_ls_cmd() {
5757
QmSix55yz8CzWXf5ZVM9vgEvijnEeeXiTSarVtsqiiCJss:
5858
QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe File 128 128
5959
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN File 6 a
60-
6160
EOF
6261
test_cmp expected_ls actual_ls
6362
'
@@ -84,10 +83,21 @@ test_ls_cmd() {
8483
Hash Type Size Name
8584
QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe File 128 128
8685
QmZULkCELmmk5XNfCgTnCyFgAVxBRBXyDHGGMVoLFLiXEN File 6 a
87-
8886
EOF
8987
test_cmp expected_ls_headers actual_ls_headers
9088
'
89+
90+
test_expect_success "'ipfs unixfs ls <file hashes>' succeeds" '
91+
ipfs unixfs ls /ipfs/QmR3jhV4XpxxPjPT3Y8vNnWvWNvakdcT3H6vqpRBsX1MLy/1024 QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe >actual_ls_file
92+
'
93+
94+
test_expect_success "'ipfs unixfs ls <file hashes>' output looks good" '
95+
cat <<-\EOF >expected_ls_file &&
96+
QmbQBUSRL9raZtNXfpTDeaxQapibJEG6qEY8WqAN22aUzd File 1024 /ipfs/QmR3jhV4XpxxPjPT3Y8vNnWvWNvakdcT3H6vqpRBsX1MLy/1024
97+
QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe File 128 QmQNd6ubRXaNG6Prov8o6vk3bn6eWsj9FxLGrAVDUAGkGe
98+
EOF
99+
test_cmp expected_ls_file actual_ls_file
100+
'
91101
}
92102

93103
# should work offline

0 commit comments

Comments
 (0)