mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-26 12:57:44 +08:00
218 lines
4.4 KiB
Go
218 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"runtime/pprof"
|
|
|
|
cmds "github.com/jbenet/go-ipfs/commands"
|
|
cmdsCli "github.com/jbenet/go-ipfs/commands/cli"
|
|
cmdsHttp "github.com/jbenet/go-ipfs/commands/http"
|
|
"github.com/jbenet/go-ipfs/config"
|
|
"github.com/jbenet/go-ipfs/core"
|
|
commands "github.com/jbenet/go-ipfs/core/commands2"
|
|
daemon "github.com/jbenet/go-ipfs/daemon2"
|
|
u "github.com/jbenet/go-ipfs/util"
|
|
)
|
|
|
|
// log is the command logger
|
|
var log = u.Logger("cmd/ipfs")
|
|
|
|
func main() {
|
|
args := os.Args[1:]
|
|
req, root := createRequest(args)
|
|
handleOptions(req, root)
|
|
res := callCommand(req, root)
|
|
outputResponse(res)
|
|
}
|
|
|
|
func createRequest(args []string) (cmds.Request, *cmds.Command) {
|
|
req, root, err := cmdsCli.Parse(args, Root, commands.Root)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
fmt.Println(Root.Help)
|
|
os.Exit(1)
|
|
}
|
|
|
|
options, err := getOptions(req, root)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
configPath, err := getConfigRoot(options)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
conf, err := getConfig(configPath)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
ctx := req.Context()
|
|
ctx.ConfigRoot = configPath
|
|
ctx.Config = conf
|
|
|
|
if _, found := options.Option("encoding"); !found {
|
|
if req.Command().Marshallers != nil && req.Command().Marshallers[cmds.Text] != nil {
|
|
req.SetOption("encoding", cmds.Text)
|
|
} else {
|
|
req.SetOption("encoding", cmds.JSON)
|
|
}
|
|
}
|
|
|
|
return req, root
|
|
}
|
|
|
|
func handleOptions(req cmds.Request, root *cmds.Command) {
|
|
options, err := getOptions(req, root)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if help, found := options.Option("help"); found {
|
|
if helpBool, ok := help.(bool); helpBool && ok {
|
|
fmt.Println(req.Command().Help)
|
|
os.Exit(0)
|
|
} else if !ok {
|
|
fmt.Println("error: expected 'help' option to be a bool")
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
if debug, found := options.Option("debug"); found {
|
|
if debugBool, ok := debug.(bool); debugBool && ok {
|
|
u.Debug = true
|
|
|
|
// if debugging, setup profiling.
|
|
if u.Debug {
|
|
ofi, err := os.Create("cpu.prof")
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
pprof.StartCPUProfile(ofi)
|
|
defer ofi.Close()
|
|
defer pprof.StopCPUProfile()
|
|
}
|
|
} else if !ok {
|
|
fmt.Println("error: expected 'debug' option to be a bool")
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
}
|
|
|
|
func callCommand(req cmds.Request, root *cmds.Command) cmds.Response {
|
|
var res cmds.Response
|
|
|
|
if root == Root {
|
|
res = root.Call(req)
|
|
|
|
} else {
|
|
options, err := getOptions(req, root)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
var found bool
|
|
var local interface{}
|
|
localBool := false
|
|
if local, found = options.Option("local"); found {
|
|
var ok bool
|
|
localBool, ok = local.(bool)
|
|
if !ok {
|
|
fmt.Println("error: expected 'local' option to be a bool")
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
if (!found || !localBool) && daemon.Locked(req.Context().ConfigRoot) {
|
|
res, err = cmdsHttp.Send(req)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
} else {
|
|
node, err := core.NewIpfsNode(req.Context().Config, false)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
req.Context().Node = node
|
|
|
|
res = root.Call(req)
|
|
}
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
func outputResponse(res cmds.Response) {
|
|
if res.Error() != nil {
|
|
fmt.Println(res.Error().Error())
|
|
|
|
if res.Request().Command().Help != "" && res.Error().Code == cmds.ErrClient {
|
|
// TODO: convert from markdown to ANSI terminal format?
|
|
fmt.Println(res.Request().Command().Help)
|
|
}
|
|
|
|
os.Exit(1)
|
|
}
|
|
|
|
out, err := res.Reader()
|
|
if err != nil {
|
|
fmt.Println(err.Error())
|
|
return
|
|
}
|
|
|
|
io.Copy(os.Stdout, out)
|
|
}
|
|
|
|
func getOptions(req cmds.Request, root *cmds.Command) (cmds.Request, error) {
|
|
tempReq := cmds.NewRequest(req.Path(), req.Options(), nil, nil)
|
|
|
|
options, err := root.GetOptions(tempReq.Path())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tempReq.ConvertOptions(options)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return tempReq, nil
|
|
}
|
|
|
|
func getConfigRoot(req cmds.Request) (string, error) {
|
|
if opt, found := req.Option("config"); found {
|
|
if optStr, ok := opt.(string); ok {
|
|
return optStr, nil
|
|
} else {
|
|
return "", fmt.Errorf("Expected 'config' option to be a string")
|
|
}
|
|
}
|
|
|
|
configPath, err := config.PathRoot()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return configPath, nil
|
|
}
|
|
|
|
func getConfig(path string) (*config.Config, error) {
|
|
configFile, err := config.Filename(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return config.Load(configFile)
|
|
}
|