diff --git a/core/coreapi/interface/options/unixfs.go b/core/coreapi/interface/options/unixfs.go new file mode 100644 index 000000000..8dc9806a7 --- /dev/null +++ b/core/coreapi/interface/options/unixfs.go @@ -0,0 +1,50 @@ +package options + +import ( + mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" +) + +type UnixfsAddSettings struct { + CidVersion int + MhType uint64 + + InlineLimit int +} + +type UnixfsAddOption func(*UnixfsAddSettings) error + +func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, error) { + options := &UnixfsAddSettings{ + CidVersion: -1, + MhType: mh.SHA2_256, + + InlineLimit: 0, + } + + for _, opt := range opts { + err := opt(options) + if err != nil { + return nil, err + } + } + + return options, nil +} + +type unixfsOpts struct{} + +var Unixfs unixfsOpts + +func (unixfsOpts) CidVersion(version int) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.CidVersion = version + return nil + } +} + +func (unixfsOpts) Hash(mhtype uint64) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.MhType = mhtype + return nil + } +} diff --git a/core/coreapi/interface/unixfs.go b/core/coreapi/interface/unixfs.go index 4a3aff6fc..10febd9fa 100644 --- a/core/coreapi/interface/unixfs.go +++ b/core/coreapi/interface/unixfs.go @@ -4,13 +4,15 @@ import ( "context" "io" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" + ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) // UnixfsAPI is the basic interface to immutable files in IPFS type UnixfsAPI interface { // Add imports the data from the reader into merkledag file - Add(context.Context, io.Reader) (ResolvedPath, error) + Add(context.Context, io.ReadCloser, ...options.UnixfsAddOption) (ResolvedPath, error) // Cat returns a reader for the file Cat(context.Context, Path) (Reader, error) diff --git a/core/coreapi/name_test.go b/core/coreapi/name_test.go index d22666484..650d487b4 100644 --- a/core/coreapi/name_test.go +++ b/core/coreapi/name_test.go @@ -3,6 +3,7 @@ package coreapi_test import ( "context" "io" + "io/ioutil" "math/rand" "testing" "time" @@ -16,7 +17,7 @@ import ( var rnd = rand.New(rand.NewSource(0x62796532303137)) func addTestObject(ctx context.Context, api coreiface.CoreAPI) (coreiface.Path, error) { - return api.Unixfs().Add(ctx, &io.LimitedReader{R: rnd, N: 4092}) + return api.Unixfs().Add(ctx, ioutil.NopCloser(&io.LimitedReader{R: rnd, N: 4092})) } func TestBasicPublishResolve(t *testing.T) { diff --git a/core/coreapi/pin_test.go b/core/coreapi/pin_test.go index 9bbf16c9c..fbae22802 100644 --- a/core/coreapi/pin_test.go +++ b/core/coreapi/pin_test.go @@ -2,6 +2,7 @@ package coreapi_test import ( "context" + "io/ioutil" "strings" "testing" @@ -15,7 +16,7 @@ func TestPinAdd(t *testing.T) { t.Error(err) } - p, err := api.Unixfs().Add(ctx, strings.NewReader("foo")) + p, err := api.Unixfs().Add(ctx, ioutil.NopCloser(strings.NewReader("foo"))) if err != nil { t.Error(err) } @@ -33,7 +34,7 @@ func TestPinSimple(t *testing.T) { t.Error(err) } - p, err := api.Unixfs().Add(ctx, strings.NewReader("foo")) + p, err := api.Unixfs().Add(ctx, ioutil.NopCloser(strings.NewReader("foo"))) if err != nil { t.Error(err) } @@ -82,12 +83,12 @@ func TestPinRecursive(t *testing.T) { t.Error(err) } - p0, err := api.Unixfs().Add(ctx, strings.NewReader("foo")) + p0, err := api.Unixfs().Add(ctx, ioutil.NopCloser(strings.NewReader("foo"))) if err != nil { t.Error(err) } - p1, err := api.Unixfs().Add(ctx, strings.NewReader("bar")) + p1, err := api.Unixfs().Add(ctx, ioutil.NopCloser(strings.NewReader("bar"))) if err != nil { t.Error(err) } diff --git a/core/coreapi/unixfs.go b/core/coreapi/unixfs.go index 1a2479ab9..27962202e 100644 --- a/core/coreapi/unixfs.go +++ b/core/coreapi/unixfs.go @@ -5,10 +5,12 @@ import ( "io" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" coreunix "github.com/ipfs/go-ipfs/core/coreunix" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" + uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) @@ -16,16 +18,44 @@ type UnixfsAPI CoreAPI // Add builds a merkledag node from a reader, adds it to the blockstore, // and returns the key representing that node. -func (api *UnixfsAPI) Add(ctx context.Context, r io.Reader) (coreiface.ResolvedPath, error) { - k, err := coreunix.AddWithContext(ctx, api.node, r) +func (api *UnixfsAPI) Add(ctx context.Context, r io.ReadCloser, opts ...options.UnixfsAddOption) (coreiface.ResolvedPath, error) { + _, err := options.UnixfsAddOptions(opts...) if err != nil { return nil, err } - c, err := cid.Decode(k) + + outChan := make(chan interface{}, 1) + + fileAdder, err := coreunix.NewAdder(ctx, api.node.Pinning, api.node.Blockstore, api.node.DAG) if err != nil { return nil, err } - return coreiface.IpfsPath(c), nil + + fileAdder.Out = outChan + + err = fileAdder.AddFile(files.NewReaderFile("", "", r, nil)) + if err != nil { + return nil, err + } + + if _, err = fileAdder.Finalize(); err != nil { + return nil, err + } + + for { + select { + case r := <-outChan: + output := r.(*coreunix.AddedObject) + if output.Hash != "" { + c, err := cid.Parse(output.Hash) + if err != nil { + return nil, err + } + + return coreiface.IpfsPath(c), err + } + } + } } // Cat returns the data contained by an IPFS or IPNS object(s) at path `p`. diff --git a/core/coreapi/unixfs_test.go b/core/coreapi/unixfs_test.go index bc78448f5..e7c6d1537 100644 --- a/core/coreapi/unixfs_test.go +++ b/core/coreapi/unixfs_test.go @@ -6,6 +6,7 @@ import ( "encoding/base64" "fmt" "io" + "io/ioutil" "math" "strings" "testing" @@ -133,7 +134,7 @@ func TestAdd(t *testing.T) { } str := strings.NewReader(helloStr) - p, err := api.Unixfs().Add(ctx, str) + p, err := api.Unixfs().Add(ctx, ioutil.NopCloser(str)) if err != nil { t.Error(err) } @@ -165,7 +166,7 @@ func TestAddEmptyFile(t *testing.T) { } str := strings.NewReader("") - p, err := api.Unixfs().Add(ctx, str) + p, err := api.Unixfs().Add(ctx, ioutil.NopCloser(str)) if err != nil { t.Error(err) }