<commit_before>package main

import (
	"fmt"
	"io"
	"os"
	"os/signal"
	"runtime/pprof"

	logging "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-logging"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
	manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"

	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")

const (
	heapProfile = "ipfs.mprof"
	errorFormat = "ERROR: %v\n\n"
)

var ofi io.WriteCloser

func main() {
	handleInterrupt()

	args := os.Args[1:]
	req, root := createRequest(args)
	handleOptions(req, root)

	// if debugging, setup profiling.
	if u.Debug {
		var err error
		ofi, err = os.Create("cpu.prof")
		if err != nil {
			fmt.Println(err)
			return
		}

		pprof.StartCPUProfile(ofi)
	}

	res := callCommand(req, root)
	outputResponse(res, root)

	exit(0)
}

func createRequest(args []string) (cmds.Request, *cmds.Command) {
	req, root, cmd, path, err := cmdsCli.Parse(args, Root, commands.Root)

	var options cmds.Request
	if req != nil && root != nil {
		var err2 error
		options, err2 = getOptions(req, root)
		if err2 != nil {
			fmt.Println(err2)
			exit(1)
		}
	}

	// handle parse error (which means the commandline input was wrong,
	// e.g. incorrect number of args, or nonexistent subcommand)
	if err != nil {
		// if the -help flag wasn't specified, show the error message
		// or if a path was returned (user specified a valid subcommand), show the error message
		// (this means there was an option or argument error)
		if options != nil || path != nil && len(path) > 0 {
			help := false
			if options != nil {
				opt, _ := options.Option("help")
				help, _ = opt.(bool)
			}

			if !help {
				fmt.Printf(errorFormat, err)
			}
		}

		// when generating help for the root command, we don't want the autogenerated subcommand text
		// (since we have better hand-made subcommand list in the root Help field)
		if cmd == nil {
			root = &*commands.Root
			root.Subcommands = nil
		}

		// generate the help text for the command the user was trying to call (or root)
		helpText, err := cmdsCli.HelpText("ipfs", root, path)
		if err != nil {
			fmt.Println(err)
		} else {
			fmt.Println(helpText)
		}
		exit(1)
	}

	configPath, err := getConfigRoot(options)
	if err != nil {
		fmt.Println(err)
		exit(1)
	}

	conf, err := getConfig(configPath)
	if err != nil {
		fmt.Println(err)
		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)
		exit(1)
	}

	if help, found := options.Option("help"); found {
		if helpBool, ok := help.(bool); helpBool && ok {
			helpText, err := cmdsCli.HelpText("ipfs", root, req.Path())
			if err != nil {
				fmt.Println(err.Error())
			} else {
				fmt.Println(helpText)
			}
			exit(0)
		} else if !ok {
			fmt.Println("error: expected 'help' option to be a bool")
			exit(1)
		}
	}

	if debug, found := options.Option("debug"); found {
		if debugBool, ok := debug.(bool); debugBool && ok {
			u.Debug = true

			u.SetAllLoggers(logging.DEBUG)
		} else if !ok {
			fmt.Println("error: expected 'debug' option to be a bool")
			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)
			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")
				exit(1)
			}
		}

		if (!found || !localBool) && daemon.Locked(req.Context().ConfigRoot) {
			addr, err := ma.NewMultiaddr(req.Context().Config.Addresses.API)
			if err != nil {
				fmt.Println(err)
				exit(1)
			}

			_, host, err := manet.DialArgs(addr)
			if err != nil {
				fmt.Println(err)
				exit(1)
			}

			client := cmdsHttp.NewClient(host)

			res, err = client.Send(req)
			if err != nil {
				fmt.Println(err)
				exit(1)
			}

		} else {
			node, err := core.NewIpfsNode(req.Context().Config, false)
			if err != nil {
				fmt.Println(err)
				exit(1)
			}
			defer node.Close()
			req.Context().Node = node

			res = root.Call(req)
		}
	}

	return res
}

func outputResponse(res cmds.Response, root *cmds.Command) {
	if res.Error() != nil {
		fmt.Printf(errorFormat, res.Error().Error())

		if res.Error().Code == cmds.ErrClient {
			helpText, err := cmdsCli.HelpText("ipfs", root, res.Request().Path())
			if err != nil {
				fmt.Println(err.Error())
			} else {
				fmt.Println(helpText)
			}
		}

		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<commit_msg>cmd/ipfs2: Cleaned up main option checking (no longer need temporary Request)<commit_after>package main

import (
	"fmt"
	"io"
	"os"
	"os/signal"
	"runtime/pprof"

	logging "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-logging"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
	manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"

	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")

const (
	heapProfile = "ipfs.mprof"
	errorFormat = "ERROR: %v\n\n"
)

var ofi io.WriteCloser

func main() {
	handleInterrupt()

	args := os.Args[1:]
	req, root := createRequest(args)
	handleOptions(req, root)

	// if debugging, setup profiling.
	if u.Debug {
		var err error
		ofi, err = os.Create("cpu.prof")
		if err != nil {
			fmt.Println(err)
			return
		}

		pprof.StartCPUProfile(ofi)
	}

	res := callCommand(req, root)
	outputResponse(res, root)

	exit(0)
}

func createRequest(args []string) (cmds.Request, *cmds.Command) {
	req, root, cmd, path, err := cmdsCli.Parse(args, Root, commands.Root)

	// handle parse error (which means the commandline input was wrong,
	// e.g. incorrect number of args, or nonexistent subcommand)
	if err != nil {
		// if the -help flag wasn't specified, show the error message
		// or if a path was returned (user specified a valid subcommand), show the error message
		// (this means there was an option or argument error)
		if path != nil && len(path) > 0 {
			help := false
			opt, _ := req.Option("help")
			help, _ = opt.(bool)

			if !help {
				fmt.Printf(errorFormat, err)
			}
		}

		// when generating help for the root command, we don't want the autogenerated subcommand text
		// (since we have better hand-made subcommand list in the root Help field)
		if cmd == nil {
			root = &*commands.Root
			root.Subcommands = nil
		}

		// generate the help text for the command the user was trying to call (or root)
		helpText, err := cmdsCli.HelpText("ipfs", root, path)
		if err != nil {
			fmt.Println(err)
		} else {
			fmt.Println(helpText)
		}
		exit(1)
	}

	configPath, err := getConfigRoot(req)
	if err != nil {
		fmt.Println(err)
		exit(1)
	}

	conf, err := getConfig(configPath)
	if err != nil {
		fmt.Println(err)
		exit(1)
	}

	ctx := req.Context()
	ctx.ConfigRoot = configPath
	ctx.Config = conf

	if _, found := req.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) {
	if help, found := req.Option("help"); found {
		if helpBool, ok := help.(bool); helpBool && ok {
			helpText, err := cmdsCli.HelpText("ipfs", root, req.Path())
			if err != nil {
				fmt.Println(err.Error())
			} else {
				fmt.Println(helpText)
			}
			exit(0)
		} else if !ok {
			fmt.Println("error: expected 'help' option to be a bool")
			exit(1)
		}
	}

	if debug, found := req.Option("debug"); found {
		if debugBool, ok := debug.(bool); debugBool && ok {
			u.Debug = true

			u.SetAllLoggers(logging.DEBUG)
		} else if !ok {
			fmt.Println("error: expected 'debug' option to be a bool")
			exit(1)
		}
	}
}

func callCommand(req cmds.Request, root *cmds.Command) cmds.Response {
	var res cmds.Response

	if root == Root {
		res = root.Call(req)

	} else {
		var found bool
		var local interface{}
		localBool := false
		if local, found = req.Option("local"); found {
			var ok bool
			localBool, ok = local.(bool)
			if !ok {
				fmt.Println("error: expected 'local' option to be a bool")
				exit(1)
			}
		}

		if (!found || !localBool) && daemon.Locked(req.Context().ConfigRoot) {
			addr, err := ma.NewMultiaddr(req.Context().Config.Addresses.API)
			if err != nil {
				fmt.Println(err)
				exit(1)
			}

			_, host, err := manet.DialArgs(addr)
			if err != nil {
				fmt.Println(err)
				exit(1)
			}

			client := cmdsHttp.NewClient(host)

			res, err = client.Send(req)
			if err != nil {
				fmt.Println(err)
				exit(1)
			}

		} else {
			node, err := core.NewIpfsNode(req.Context().Config, false)
			if err != nil {
				fmt.Println(err)
				exit(1)
			}
			defer node.Close()
			req.Context().Node = node

			res = root.Call(req)
		}
	}

	return res
}

func outputResponse(res cmds.Response, root *cmds.Command) {
	if res.Error() != nil {
		fmt.Printf(errorFormat, res.Error().Error())

		if res.Error().Code == cmds.ErrClient {
			helpText, err := cmdsCli.HelpText("ipfs", root, res.Request().Path())
			if err != nil {
				fmt.Println(err.Error())
			} else {
				fmt.Println(helpText)
			}
		}

		exit(1)
	}

	out, err := res.Reader()
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	io.Copy(os.Stdout, out)
}

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
{'fraction_non_alphanumeric': 0.15143715143715145, 'fraction_numerical': 0.0036036036036036037, 'mean_word_length': 3.1539558089807556, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '608604', 'n_tokens_mistral': 4847, 'n_tokens_neox': 4330, 'n_words': 1064}