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

feat: add DagImport method #287

Merged
merged 2 commits into from
Mar 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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