make raw leaves work with 'ipfs get'
License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>
Jeromy committed
Mar 6, 2017 at 20:12 UTC
b1588c7162dcf12879980b5beb7d5ecdb9cb7770
4 files changed
+72
-43
core/commands/get.go
+14
-12
@@ -70,22 +70,24 @@ may also specify the level of compression by specifying '-l=<1-9>'.
70
return
71
}
72
73
- pbnd, ok := dn.(*dag.ProtoNode)
74
- if !ok {
75
- res.SetError(err, cmds.ErrNormal)
73
+ switch dn := dn.(type) {
74
+ case *dag.ProtoNode:
75
+ size, err := dn.Size()
76
+ if err != nil {
77
+ res.SetError(err, cmds.ErrNormal)
78
+ return
79
+ }
80
+
81
+ res.SetLength(size)
82
+ case *dag.RawNode:
83
+ res.SetLength(uint64(len(dn.RawData())))
84
+ default:
85
+ res.SetError(fmt.Errorf("'ipfs get' only supports unixfs nodes"), cmds.ErrNormal)
86
return
87
}
88
79
- size, err := dn.Size()
80
- if err != nil {
81
- res.SetError(err, cmds.ErrNormal)
82
- return
83
- }
84
-
85
- res.SetLength(size)
86
-
89
archive, _, _ := req.Option("archive").Bool()
88
- reader, err := uarchive.DagArchive(ctx, pbnd, p.String(), node.DAG, archive, cmplvl)
90
+ reader, err := uarchive.DagArchive(ctx, dn, p.String(), node.DAG, archive, cmplvl)
91
if err != nil {
92
res.SetError(err, cmds.ErrNormal)
93
return
test/sharness/t0090-get.sh
+14
@@ -64,6 +64,20 @@ test_get_cmd() {
64
rm "$HASH"
65
'
66
67
+ test_expect_success "ipfs get works with raw leaves" '
68
+ HASH2=$(ipfs add --raw-leaves -q data) &&
69
+ ipfs get "$HASH2" >actual2
70
+ '
71
+
72
+ test_expect_success "ipfs get output looks good" '
73
+ printf "%s\n\n" "Saving file(s) to $HASH2" >expected2 &&
74
+ test_cmp expected2 actual2
75
+ '
76
+
77
+ test_expect_success "ipfs get file output looks good" '
78
+ test_cmp "$HASH2" data
79
+ '
80
+
81
test_ipfs_get_flag ".tar" "-xf" -a
82
83
test_ipfs_get_flag ".tar.gz" "-zxf" -a -C
unixfs/archive/archive.go
+4
-3
@@ -3,14 +3,15 @@ package archive
3
import (
4
"bufio"
5
"compress/gzip"
6
+ "context"
7
"io"
8
"path"
9
9
- cxt "context"
10
-
10
mdag "github.com/ipfs/go-ipfs/merkledag"
11
tar "github.com/ipfs/go-ipfs/unixfs/archive/tar"
12
uio "github.com/ipfs/go-ipfs/unixfs/io"
13
+
14
+ node "gx/ipfs/QmYDscK7dmdo2GZ9aumS8s5auUUAH5mR1jvj5pYhWusfK7/go-ipld-node"
15
)
16
17
// DefaultBufSize is the buffer size for gets. for now, 1MB, which is ~4 blocks.
@@ -30,7 +31,7 @@ func (i *identityWriteCloser) Close() error {
31
}
32
33
// DagArchive is equivalent to `ipfs getdag $hash | maybe_tar | maybe_gzip`
33
-func DagArchive(ctx cxt.Context, nd *mdag.ProtoNode, name string, dag mdag.DAGService, archive bool, compression int) (io.Reader, error) {
34
+func DagArchive(ctx context.Context, nd node.Node, name string, dag mdag.DAGService, archive bool, compression int) (io.Reader, error) {
35
36
_, filename := path.Split(name)
37
unixfs/archive/tar/writer.go
+40
-28
@@ -2,17 +2,19 @@ package tar
2
3
import (
4
"archive/tar"
5
+ "context"
6
+ "fmt"
7
"io"
8
"path"
9
"time"
10
9
- cxt "context"
10
- proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
11
-
11
mdag "github.com/ipfs/go-ipfs/merkledag"
12
ft "github.com/ipfs/go-ipfs/unixfs"
13
uio "github.com/ipfs/go-ipfs/unixfs/io"
14
upb "github.com/ipfs/go-ipfs/unixfs/pb"
15
+
16
+ node "gx/ipfs/QmYDscK7dmdo2GZ9aumS8s5auUUAH5mR1jvj5pYhWusfK7/go-ipld-node"
17
+ proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
18
)
19
20
// Writer is a utility structure that helps to write
@@ -22,11 +24,11 @@ type Writer struct {
24
Dag mdag.DAGService
25
TarW *tar.Writer
26
25
- ctx cxt.Context
27
+ ctx context.Context
28
}
29
30
// NewWriter wraps given io.Writer.
29
-func NewWriter(ctx cxt.Context, dag mdag.DAGService, archive bool, compression int, w io.Writer) (*Writer, error) {
31
+func NewWriter(ctx context.Context, dag mdag.DAGService, archive bool, compression int, w io.Writer) (*Writer, error) {
32
return &Writer{
33
Dag: dag,
34
TarW: tar.NewWriter(w),
@@ -45,13 +47,8 @@ func (w *Writer) writeDir(nd *mdag.ProtoNode, fpath string) error {
47
return err
48
}
49
48
- childpb, ok := child.(*mdag.ProtoNode)
49
- if !ok {
50
- return mdag.ErrNotProtobuf
51
- }
52
-
50
npath := path.Join(fpath, nd.Links()[i].Name)
54
- if err := w.WriteNode(childpb, npath); err != nil {
51
+ if err := w.WriteNode(child, npath); err != nil {
52
return err
53
}
54
}
@@ -72,25 +69,40 @@ func (w *Writer) writeFile(nd *mdag.ProtoNode, pb *upb.Data, fpath string) error
69
return nil
70
}
71
75
-func (w *Writer) WriteNode(nd *mdag.ProtoNode, fpath string) error {
76
- pb := new(upb.Data)
77
- if err := proto.Unmarshal(nd.Data(), pb); err != nil {
78
- return err
79
- }
72
+func (w *Writer) WriteNode(nd node.Node, fpath string) error {
73
+ switch nd := nd.(type) {
74
+ case *mdag.ProtoNode:
75
+ pb := new(upb.Data)
76
+ if err := proto.Unmarshal(nd.Data(), pb); err != nil {
77
+ return err
78
+ }
79
+
80
+ switch pb.GetType() {
81
+ case upb.Data_Metadata:
82
+ fallthrough
83
+ case upb.Data_Directory:
84
+ return w.writeDir(nd, fpath)
85
+ case upb.Data_Raw:
86
+ fallthrough
87
+ case upb.Data_File:
88
+ return w.writeFile(nd, pb, fpath)
89
+ case upb.Data_Symlink:
90
+ return writeSymlinkHeader(w.TarW, string(pb.GetData()), fpath)
91
+ default:
92
+ return ft.ErrUnrecognizedType
93
+ }
94
+ case *mdag.RawNode:
95
+ if err := writeFileHeader(w.TarW, fpath, uint64(len(nd.RawData()))); err != nil {
96
+ return err
97
+ }
98
81
- switch pb.GetType() {
82
- case upb.Data_Metadata:
83
- fallthrough
84
- case upb.Data_Directory:
85
- return w.writeDir(nd, fpath)
86
- case upb.Data_Raw:
87
- fallthrough
88
- case upb.Data_File:
89
- return w.writeFile(nd, pb, fpath)
90
- case upb.Data_Symlink:
91
- return writeSymlinkHeader(w.TarW, string(pb.GetData()), fpath)
99
+ if _, err := w.TarW.Write(nd.RawData()); err != nil {
100
+ return err
101
+ }
102
+ w.TarW.Flush()
103
+ return nil
104
default:
93
- return ft.ErrUnrecognizedType
105
+ return fmt.Errorf("nodes of type %T are not supported in unixfs", nd)
106
}
107
}
108