Skip to content
This repository has been archived by the owner on Feb 7, 2024. It is now read-only.

Commit

Permalink
feat: add DagImport method (#287)
Browse files Browse the repository at this point in the history
Co-authored-by: Henrique Dias <hacdias@gmail.com>
  • Loading branch information
fabiobozzo and hacdias committed Mar 28, 2023
1 parent 82a4237 commit c356d0d
Show file tree
Hide file tree
Showing 8 changed files with 304 additions and 80 deletions.
128 changes: 112 additions & 16 deletions dag.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,41 @@ package shell
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"strings"

"github.com/ipfs/go-ipfs-api/options"
files "github.com/ipfs/go-ipfs-files"

"github.com/ipfs/go-ipfs-api/options"
)

type DagPutOutput struct {
Cid struct {
Target string `json:"/"`
}
}

type DagImportRoot struct {
Root struct {
Cid struct {
Value string `json:"/"`
}
}
Stats *DagImportStats `json:"Stats,omitempty"`
}

type DagImportStats struct {
BlockBytesCount uint64
BlockCount uint64
}

type DagImportOutput struct {
Roots []DagImportRoot
Stats *DagImportStats
}

func (s *Shell) DagGet(ref string, out interface{}) error {
return s.Request("dag/get", ref).Exec(context.Background(), out)
}
Expand All @@ -25,34 +52,103 @@ func (s *Shell) DagPutWithOpts(data interface{}, opts ...options.DagPutOption) (
return "", err
}

fileReader, err := dagToFilesReader(data)
if err != nil {
return "", err
}

var out DagPutOutput

return out.Cid.Target, s.
Request("dag/put").
Option("input-codec", cfg.InputCodec).
Option("store-codec", cfg.StoreCodec).
Option("pin", cfg.Pin).
Option("hash", cfg.Hash).
Body(fileReader).
Exec(context.Background(), &out)
}

// DagImport imports the contents of .car files (with default parameters)
func (s *Shell) DagImport(data interface{}, silent, stats bool) (*DagImportOutput, error) {
return s.DagImportWithOpts(data, options.Dag.Silent(silent), options.Dag.Stats(stats))
}

// DagImportWithOpts imports the contents of .car files
func (s *Shell) DagImportWithOpts(data interface{}, opts ...options.DagImportOption) (*DagImportOutput, error) {
cfg, err := options.DagImportOptions(opts...)
if err != nil {
return nil, err
}

fileReader, err := dagToFilesReader(data)
if err != nil {
return nil, err
}

res, err := s.Request("dag/import").
Option("pin-roots", cfg.PinRoots).
Option("silent", cfg.Silent).
Option("stats", cfg.Stats).
Option("allow-big-block", cfg.AllowBigBlock).
Body(fileReader).
Send(context.Background())
if err != nil {
return nil, err
}
defer res.Close()

if res.Error != nil {
return nil, res.Error
}

if cfg.Silent {
return nil, nil
}

out := DagImportOutput{
Roots: []DagImportRoot{},
}

dec := json.NewDecoder(res.Output)

for {
var root DagImportRoot
err := dec.Decode(&root)
if err == io.EOF {
break
}

if root.Stats != nil {
out.Stats = root.Stats

break
}

out.Roots = append(out.Roots, root)
}

return &out, err
}

func dagToFilesReader(data interface{}) (*files.MultiFileReader, error) {
var r io.Reader
switch data := data.(type) {
case *files.MultiFileReader:
return data, nil
case string:
r = strings.NewReader(data)
case []byte:
r = bytes.NewReader(data)
case io.Reader:
r = data
default:
return "", fmt.Errorf("cannot current handle putting values of type %T", data)
return nil, fmt.Errorf("values of type %T cannot be handled as DAG input", data)
}

fr := files.NewReaderFile(r)
slf := files.NewSliceDirectory([]files.DirEntry{files.FileEntry("", fr)})
fileReader := files.NewMultiFileReader(slf, true)

var out struct {
Cid struct {
Target string `json:"/"`
}
}

return out.Cid.Target, s.
Request("dag/put").
Option("input-codec", cfg.InputCodec).
Option("store-codec", cfg.StoreCodec).
Option("pin", cfg.Pin).
Option("hash", cfg.Hash).
Body(fileReader).
Exec(context.Background(), &out)
return fileReader, nil
}
64 changes: 0 additions & 64 deletions options/dag.go
Original file line number Diff line number Diff line change
@@ -1,69 +1,5 @@
package options

// DagPutSettings is a set of DagPut options.
type DagPutSettings struct {
InputCodec string
StoreCodec string
Pin string
Hash string
}

// DagPutOption is a single DagPut option.
type DagPutOption func(opts *DagPutSettings) error

// DagPutOptions applies the given options to a DagPutSettings instance.
func DagPutOptions(opts ...DagPutOption) (*DagPutSettings, error) {
options := &DagPutSettings{
InputCodec: "dag-json",
StoreCodec: "dag-cbor",
Pin: "false",
Hash: "sha2-256",
}

for _, opt := range opts {
err := opt(options)
if err != nil {
return nil, err
}
}
return options, nil
}

type dagOpts struct{}

var Dag dagOpts

// Pin is an option for Dag.Put which specifies whether to pin the added
// dags. Default is "false".
func (dagOpts) Pin(pin string) DagPutOption {
return func(opts *DagPutSettings) error {
opts.Pin = pin
return nil
}
}

// InputCodec is an option for Dag.Put which specifies the input encoding of the
// data. Default is "dag-json".
func (dagOpts) InputCodec(codec string) DagPutOption {
return func(opts *DagPutSettings) error {
opts.InputCodec = codec
return nil
}
}

// StoreCodec is an option for Dag.Put which specifies the codec that the stored
// object will be encoded with. Default is "dag-cbor".
func (dagOpts) StoreCodec(codec string) DagPutOption {
return func(opts *DagPutSettings) error {
opts.StoreCodec = codec
return nil
}
}

// Hash is an option for Dag.Put which specifies the hash function to use
func (dagOpts) Hash(hash string) DagPutOption {
return func(opts *DagPutSettings) error {
opts.Hash = hash
return nil
}
}
72 changes: 72 additions & 0 deletions options/dag_import.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package options

// DagImportSettings is a set of DagImport options.
type DagImportSettings struct {
PinRoots bool
Silent bool
Stats bool
AllowBigBlock bool
}

// DagImportOption is a single DagImport option.
type DagImportOption func(opts *DagImportSettings) error

// DagImportOptions applies the given options to a DagImportSettings instance.
func DagImportOptions(opts ...DagImportOption) (*DagImportSettings, error) {
options := &DagImportSettings{
PinRoots: true,
Silent: false,
Stats: false,
AllowBigBlock: false,
}

for _, opt := range opts {
err := opt(options)
if err != nil {
return nil, err
}
}

return options, nil
}

// PinRoots is an option for Dag.Import which specifies whether to
// pin the optional roots listed in the .car headers after importing.
// Default is true.
func (dagOpts) PinRoots(pinRoots bool) DagImportOption {
return func(opts *DagImportSettings) error {
opts.PinRoots = pinRoots
return nil
}
}

// Silent is an option for Dag.Import which specifies whether to
// return any output or not.
// Default is false.
func (dagOpts) Silent(silent bool) DagImportOption {
return func(opts *DagImportSettings) error {
opts.Silent = silent
return nil
}
}

// Stats is an option for Dag.Import which specifies whether to
// return stats about the import operation.
// Default is false.
func (dagOpts) Stats(stats bool) DagImportOption {
return func(opts *DagImportSettings) error {
opts.Stats = stats
return nil
}
}

// AllowBigBlock is an option for Dag.Import which disables block size check
// and allow creation of blocks bigger than 1MiB.
// WARNING: such blocks won't be transferable over the standard bitswap.
// Default is false.
func (dagOpts) AllowBigBlock(allowBigBlock bool) DagImportOption {
return func(opts *DagImportSettings) error {
opts.AllowBigBlock = allowBigBlock
return nil
}
}
65 changes: 65 additions & 0 deletions options/dag_put.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package options

// DagPutSettings is a set of Dag options.
type DagPutSettings struct {
InputCodec string
StoreCodec string
Pin string
Hash string
}

// DagPutOption is a single Dag option.
type DagPutOption func(opts *DagPutSettings) error

// DagPutOptions applies the given options to a DagPutSettings instance.
func DagPutOptions(opts ...DagPutOption) (*DagPutSettings, error) {
options := &DagPutSettings{
InputCodec: "dag-json",
StoreCodec: "dag-cbor",
Pin: "false",
Hash: "sha2-256",
}

for _, opt := range opts {
err := opt(options)
if err != nil {
return nil, err
}
}
return options, nil
}

// Pin is an option for Dag.Put which specifies whether to pin the added
// dags. Default is "false".
func (dagOpts) Pin(pin string) DagPutOption {
return func(opts *DagPutSettings) error {
opts.Pin = pin
return nil
}
}

// InputCodec is an option for Dag.Put which specifies the input encoding of the
// data. Default is "dag-json".
func (dagOpts) InputCodec(codec string) DagPutOption {
return func(opts *DagPutSettings) error {
opts.InputCodec = codec
return nil
}
}

// StoreCodec is an option for Dag.Put which specifies the codec that the stored
// object will be encoded with. Default is "dag-cbor".
func (dagOpts) StoreCodec(codec string) DagPutOption {
return func(opts *DagPutSettings) error {
opts.StoreCodec = codec
return nil
}
}

// Hash is an option for Dag.Put which specifies the hash function to use
func (dagOpts) Hash(hash string) DagPutOption {
return func(opts *DagPutSettings) error {
opts.Hash = hash
return nil
}
}
Loading

0 comments on commit c356d0d

Please sign in to comment.