@cryptotaxi247 / kubo / commits / b1588c716

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