From 3e062f6e1ed31ae45ca619ac4a2813a9f6a86440 Mon Sep 17 00:00:00 2001
From: Matt Bell <mappum@gmail.com>
Date: Thu, 23 Oct 2014 16:35:40 -0700
Subject: [PATCH] cmd/ipfs: Rewrote entry point to invoke commands via new
 command API

---
 cmd/ipfs/ipfs.go | 220 ++++++++---------------------------------------
 1 file changed, 34 insertions(+), 186 deletions(-)

diff --git a/cmd/ipfs/ipfs.go b/cmd/ipfs/ipfs.go
index 9ce5d7faf..a37a44e7b 100644
--- a/cmd/ipfs/ipfs.go
+++ b/cmd/ipfs/ipfs.go
@@ -1,220 +1,68 @@
 package main
 
 import (
-	"errors"
 	"fmt"
+	"io"
 	"os"
 	"runtime/pprof"
 
-	flag "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
-	commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
-	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
-
-	config "github.com/jbenet/go-ipfs/config"
-	core "github.com/jbenet/go-ipfs/core"
-	daemon "github.com/jbenet/go-ipfs/daemon"
-	updates "github.com/jbenet/go-ipfs/updates"
+	cmds "github.com/jbenet/go-ipfs/commands"
+	"github.com/jbenet/go-ipfs/commands/cli"
+	"github.com/jbenet/go-ipfs/core/commands"
 	u "github.com/jbenet/go-ipfs/util"
 )
 
-// The IPFS command tree. It is an instance of `commander.Command`.
-var CmdIpfs = &commander.Command{
-	UsageLine: "ipfs [<flags>] <command> [<args>]",
-	Short:     "global versioned p2p merkledag file system",
-	Long: `ipfs - global versioned p2p merkledag file system
-
-Basic commands:
-
-    init          Initialize ipfs local configuration.
-    add <path>    Add an object to ipfs.
-    cat <ref>     Show ipfs object data.
-    ls <ref>      List links from an object.
-    refs <ref>    List link hashes from an object.
-
-Tool commands:
-
-    config        Manage configuration.
-    update        Download and apply go-ipfs updates.
-    version       Show ipfs version information.
-    commands      List all available commands.
-
-Advanced Commands:
-
-    mount         Mount an ipfs read-only mountpoint.
-    serve         Serve an interface to ipfs.
-    net-diag      Print network diagnostic
-
-Plumbing commands:
-
-    block         Interact with raw blocks in the datastore
-    object        Interact with raw dag nodes
-
-
-Use "ipfs help <command>" for more information about a command.
-`,
-	Run: ipfsCmd,
-	Subcommands: []*commander.Command{
-		cmdIpfsAdd,
-		cmdIpfsCat,
-		cmdIpfsLs,
-		cmdIpfsRefs,
-		cmdIpfsConfig,
-		cmdIpfsVersion,
-		cmdIpfsCommands,
-		cmdIpfsMount,
-		cmdIpfsInit,
-		cmdIpfsServe,
-		cmdIpfsRun,
-		cmdIpfsName,
-		cmdIpfsBootstrap,
-		cmdIpfsDiag,
-		cmdIpfsBlock,
-		cmdIpfsObject,
-		cmdIpfsUpdate,
-		cmdIpfsLog,
-		cmdIpfsPin,
-		cmdIpfsTour,
-	},
-	Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
-}
-
 // log is the command logger
 var log = u.Logger("cmd/ipfs")
 
-func init() {
-	config, err := config.PathRoot()
-	if err != nil {
-		fmt.Fprintln(os.Stderr, "Failure initializing the default Config Directory: ", err)
-		os.Exit(1)
-	}
-	CmdIpfs.Flag.String("c", config, "specify config directory")
-}
-
-func ipfsCmd(c *commander.Command, args []string) error {
-	u.POut(c.Long)
-	return nil
-}
+const API_PATH = "/api/v0"
 
 func main() {
-	// 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()
-	}
-
-	err := CmdIpfs.Dispatch(os.Args[1:])
+	req, err := cli.Parse(os.Args[1:], commands.Root)
 	if err != nil {
-		if len(err.Error()) > 0 {
-			fmt.Fprintf(os.Stderr, "ipfs %s: %v\n", os.Args[1], err)
-		}
+		fmt.Println(err)
 		os.Exit(1)
 	}
-	return
-}
 
-// localNode constructs a node
-func localNode(confdir string, online bool) (*core.IpfsNode, error) {
-	filename, err := config.Filename(confdir)
+	cmd, err := commands.Root.Get(req.Path())
 	if err != nil {
-		return nil, err
-	}
-
-	cfg, err := config.Load(filename)
-	if err != nil {
-		return nil, err
-	}
-
-	if err := updates.CliCheckForUpdates(cfg, filename); err != nil {
-		return nil, err
-	}
-
-	return core.NewIpfsNode(cfg, online)
-}
-
-// Gets the config "-c" flag from the command, or returns
-// the default configuration root directory
-func getConfigDir(c *commander.Command) (string, error) {
-
-	// use the root cmd (that's where config is specified)
-	for ; c.Parent != nil; c = c.Parent {
-	}
-
-	// flag should be defined on root.
-	param := c.Flag.Lookup("c").Value.Get().(string)
-	if param != "" {
-		return u.TildeExpansion(param)
-	}
-
-	return config.PathRoot()
-}
-
-func getConfig(c *commander.Command) (*config.Config, error) {
-	confdir, err := getConfigDir(c)
-	if err != nil {
-		return nil, err
-	}
-
-	filename, err := config.Filename(confdir)
-	if err != nil {
-		return nil, err
+		fmt.Println(err)
+		os.Exit(1)
 	}
 
-	return config.Load(filename)
-}
-
-// cmdContext is a wrapper structure that keeps a node, a daemonlistener, and
-// a config directory together. These three are needed for most commands.
-type cmdContext struct {
-	node      *core.IpfsNode
-	daemon    *daemon.DaemonListener
-	configDir string
-}
+	// TODO: send request to daemon via HTTP API
 
-// setupCmdContext initializes a cmdContext structure from a given command.
-func setupCmdContext(c *commander.Command, online bool) (cc cmdContext, err error) {
-	rootCmd := c
-	for ; rootCmd.Parent != nil; rootCmd = rootCmd.Parent {
-	}
+	if debug, ok := req.Option("debug"); ok && debug.(bool) {
+		u.Debug = true
 
-	cc.configDir, err = getConfigDir(rootCmd)
-	if err != nil {
-		return
+		// 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()
+		}
 	}
 
-	cc.node, err = localNode(cc.configDir, online)
-	if err != nil {
-		return
-	}
+	res := commands.Root.Call(req)
 
-	cc.daemon, err = setupDaemon(cc.configDir, cc.node)
-	if err != nil {
-		return
-	}
-
-	return
-}
+	if res.Error() != nil {
+		fmt.Println(res.Error().Error())
 
-// setupDaemon sets up the daemon corresponding to given node.
-func setupDaemon(confdir string, node *core.IpfsNode) (*daemon.DaemonListener, error) {
-	if node.Config.Addresses.API == "" {
-		return nil, errors.New("no config.Addresses.API endpoint supplied")
-	}
+		if cmd.Help != "" && res.Error().Code == cmds.ErrClient {
+			// TODO: convert from markdown to ANSI terminal format?
+			fmt.Println(cmd.Help)
+		}
 
-	maddr, err := ma.NewMultiaddr(node.Config.Addresses.API)
-	if err != nil {
-		return nil, err
+		os.Exit(1)
 	}
 
-	dl, err := daemon.NewDaemonListener(node, maddr, confdir)
+	_, err = io.Copy(os.Stdout, res)
 	if err != nil {
-		return nil, err
+		fmt.Println(err.Error())
 	}
-	go dl.Listen()
-	return dl, nil
 }
-- 
GitLab