mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-22 19:07:48 +08:00
147 lines
2.6 KiB
Go
147 lines
2.6 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
|
|
config "github.com/ipfs/go-ipfs-config"
|
|
"github.com/ipfs/go-ipfs-http-client"
|
|
"github.com/ipfs/interface-go-ipfs-core"
|
|
"github.com/mitchellh/go-homedir"
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/ipfs/go-ipfs/core"
|
|
"github.com/ipfs/go-ipfs/core/coreapi"
|
|
"github.com/ipfs/go-ipfs/repo/fsrepo"
|
|
)
|
|
|
|
const (
|
|
DefaultPathName = ".ipfs"
|
|
DefaultPathRoot = "~/" + DefaultPathName
|
|
EnvDir = "IPFS_PATH"
|
|
)
|
|
|
|
func repo() (string, error) {
|
|
baseDir := os.Getenv(EnvDir)
|
|
if baseDir == "" {
|
|
baseDir = DefaultPathRoot
|
|
}
|
|
return homedir.Expand(baseDir)
|
|
}
|
|
|
|
//////////////////////
|
|
|
|
type ManagedApi interface {
|
|
iface.CoreAPI
|
|
|
|
io.Closer
|
|
}
|
|
|
|
type ctxApi struct {
|
|
iface.CoreAPI
|
|
context.CancelFunc
|
|
}
|
|
|
|
func (a *ctxApi) Close() error {
|
|
a.CancelFunc()
|
|
return nil
|
|
}
|
|
|
|
var _ ManagedApi = &ctxApi{}
|
|
|
|
//////////////////////
|
|
|
|
func embedded(repoPath string) (ManagedApi, error) {
|
|
ctx, cancel := context.WithCancel(context.TODO())
|
|
|
|
r, err := fsrepo.Open(repoPath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("opening fsrepo failed: %s", err)
|
|
}
|
|
n, err := core.NewNode(ctx, &core.BuildCfg{
|
|
Online: true,
|
|
Repo: r,
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("ipfs NewNode() failed: %s", err)
|
|
}
|
|
|
|
api, err := coreapi.NewCoreAPI(n)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &ctxApi{
|
|
CoreAPI: api,
|
|
CancelFunc: cancel,
|
|
}, nil
|
|
}
|
|
|
|
type ApiProvider func() (ManagedApi, error)
|
|
|
|
var localApi ApiProvider = func() (ManagedApi, error) {
|
|
api, err := httpapi.NewLocalApi()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &ctxApi{
|
|
CoreAPI: api,
|
|
CancelFunc: func() {},
|
|
}, nil
|
|
}
|
|
|
|
var tempEmbedded ApiProvider = func() (ManagedApi, error) {
|
|
dir, err := ioutil.TempDir("", "ipfs-shell")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get temp dir: %s", err)
|
|
}
|
|
|
|
cfg, err := config.Init(ioutil.Discard, 1024)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = fsrepo.Init(dir, cfg)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to init ephemeral node: %s", err)
|
|
}
|
|
|
|
return embedded(dir)
|
|
}
|
|
|
|
var localEmbedded ApiProvider = func() (ManagedApi, error) {
|
|
repoPath, err := repo()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return embedded(repoPath)
|
|
}
|
|
|
|
// TODO: socket activation? 'manual' daemon spawning?
|
|
// TODO: repo (config?) option to tell apps to not spawn embedded nodes
|
|
|
|
// New creates new api client
|
|
func New() (iface.CoreAPI, error) {
|
|
api, err := localApi()
|
|
if api != nil || err != nil {
|
|
return api, err
|
|
}
|
|
|
|
api, err = localEmbedded()
|
|
if api != nil || err != nil {
|
|
return api, err
|
|
}
|
|
|
|
api, err = tempEmbedded()
|
|
if api != nil || err != nil {
|
|
return api, err
|
|
}
|
|
|
|
return nil, errors.New("failed to create a node")
|
|
}
|