@cryptotaxi247 / kubo / commits / 3e062f6e1

cmd/ipfs: Rewrote entry point to invoke commands via new command API

Matt Bell committed Oct 23, 2014 at 16:35 UTC 3e062f6e1ed31ae45ca619ac4a2813a9f6a86440
1 file changed +34 -186
cmd/ipfs/ipfs.go
+34 -186
@@ -1,220 +1,68 @@
1 package main
2
3 import (
4 - "errors"
4 "fmt"
5 + "io"
6 "os"
7 "runtime/pprof"
8
9 - flag "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
10 - commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
11 - ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
12 -
13 - config "github.com/jbenet/go-ipfs/config"
14 - core "github.com/jbenet/go-ipfs/core"
15 - daemon "github.com/jbenet/go-ipfs/daemon"
16 - updates "github.com/jbenet/go-ipfs/updates"
9 + cmds "github.com/jbenet/go-ipfs/commands"
10 + "github.com/jbenet/go-ipfs/commands/cli"
11 + "github.com/jbenet/go-ipfs/core/commands"
12 u "github.com/jbenet/go-ipfs/util"
13 )
14
20 -// The IPFS command tree. It is an instance of `commander.Command`.
21 -var CmdIpfs = &commander.Command{
22 - UsageLine: "ipfs [<flags>] <command> [<args>]",
23 - Short: "global versioned p2p merkledag file system",
24 - Long: `ipfs - global versioned p2p merkledag file system
25 -
26 -Basic commands:
27 -
28 - init Initialize ipfs local configuration.
29 - add <path> Add an object to ipfs.
30 - cat <ref> Show ipfs object data.
31 - ls <ref> List links from an object.
32 - refs <ref> List link hashes from an object.
33 -
34 -Tool commands:
35 -
36 - config Manage configuration.
37 - update Download and apply go-ipfs updates.
38 - version Show ipfs version information.
39 - commands List all available commands.
40 -
41 -Advanced Commands:
42 -
43 - mount Mount an ipfs read-only mountpoint.
44 - serve Serve an interface to ipfs.
45 - net-diag Print network diagnostic
46 -
47 -Plumbing commands:
48 -
49 - block Interact with raw blocks in the datastore
50 - object Interact with raw dag nodes
51 -
52 -
53 -Use "ipfs help <command>" for more information about a command.
54 -`,
55 - Run: ipfsCmd,
56 - Subcommands: []*commander.Command{
57 - cmdIpfsAdd,
58 - cmdIpfsCat,
59 - cmdIpfsLs,
60 - cmdIpfsRefs,
61 - cmdIpfsConfig,
62 - cmdIpfsVersion,
63 - cmdIpfsCommands,
64 - cmdIpfsMount,
65 - cmdIpfsInit,
66 - cmdIpfsServe,
67 - cmdIpfsRun,
68 - cmdIpfsName,
69 - cmdIpfsBootstrap,
70 - cmdIpfsDiag,
71 - cmdIpfsBlock,
72 - cmdIpfsObject,
73 - cmdIpfsUpdate,
74 - cmdIpfsLog,
75 - cmdIpfsPin,
76 - cmdIpfsTour,
77 - },
78 - Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
79 -}
80 -
15 // log is the command logger
16 var log = u.Logger("cmd/ipfs")
17
84 -func init() {
85 - config, err := config.PathRoot()
86 - if err != nil {
87 - fmt.Fprintln(os.Stderr, "Failure initializing the default Config Directory: ", err)
88 - os.Exit(1)
89 - }
90 - CmdIpfs.Flag.String("c", config, "specify config directory")
91 -}
92 -
93 -func ipfsCmd(c *commander.Command, args []string) error {
94 - u.POut(c.Long)
95 - return nil
96 -}
18 +const API_PATH = "/api/v0"
19
20 func main() {
99 - // if debugging, setup profiling.
100 - if u.Debug {
101 - ofi, err := os.Create("cpu.prof")
102 - if err != nil {
103 - fmt.Println(err)
104 - return
105 - }
106 - pprof.StartCPUProfile(ofi)
107 - defer ofi.Close()
108 - defer pprof.StopCPUProfile()
109 - }
110 -
111 - err := CmdIpfs.Dispatch(os.Args[1:])
21 + req, err := cli.Parse(os.Args[1:], commands.Root)
22 if err != nil {
113 - if len(err.Error()) > 0 {
114 - fmt.Fprintf(os.Stderr, "ipfs %s: %v\n", os.Args[1], err)
115 - }
23 + fmt.Println(err)
24 os.Exit(1)
25 }
118 - return
119 -}
26
121 -// localNode constructs a node
122 -func localNode(confdir string, online bool) (*core.IpfsNode, error) {
123 - filename, err := config.Filename(confdir)
27 + cmd, err := commands.Root.Get(req.Path())
28 if err != nil {
125 - return nil, err
126 - }
127 -
128 - cfg, err := config.Load(filename)
129 - if err != nil {
130 - return nil, err
131 - }
132 -
133 - if err := updates.CliCheckForUpdates(cfg, filename); err != nil {
134 - return nil, err
135 - }
136 -
137 - return core.NewIpfsNode(cfg, online)
138 -}
139 -
140 -// Gets the config "-c" flag from the command, or returns
141 -// the default configuration root directory
142 -func getConfigDir(c *commander.Command) (string, error) {
143 -
144 - // use the root cmd (that's where config is specified)
145 - for ; c.Parent != nil; c = c.Parent {
146 - }
147 -
148 - // flag should be defined on root.
149 - param := c.Flag.Lookup("c").Value.Get().(string)
150 - if param != "" {
151 - return u.TildeExpansion(param)
152 - }
153 -
154 - return config.PathRoot()
155 -}
156 -
157 -func getConfig(c *commander.Command) (*config.Config, error) {
158 - confdir, err := getConfigDir(c)
159 - if err != nil {
160 - return nil, err
161 - }
162 -
163 - filename, err := config.Filename(confdir)
164 - if err != nil {
165 - return nil, err
29 + fmt.Println(err)
30 + os.Exit(1)
31 }
32
168 - return config.Load(filename)
169 -}
170 -
171 -// cmdContext is a wrapper structure that keeps a node, a daemonlistener, and
172 -// a config directory together. These three are needed for most commands.
173 -type cmdContext struct {
174 - node *core.IpfsNode
175 - daemon *daemon.DaemonListener
176 - configDir string
177 -}
33 + // TODO: send request to daemon via HTTP API
34
179 -// setupCmdContext initializes a cmdContext structure from a given command.
180 -func setupCmdContext(c *commander.Command, online bool) (cc cmdContext, err error) {
181 - rootCmd := c
182 - for ; rootCmd.Parent != nil; rootCmd = rootCmd.Parent {
183 - }
35 + if debug, ok := req.Option("debug"); ok && debug.(bool) {
36 + u.Debug = true
37
185 - cc.configDir, err = getConfigDir(rootCmd)
186 - if err != nil {
187 - return
38 + // if debugging, setup profiling.
39 + if u.Debug {
40 + ofi, err := os.Create("cpu.prof")
41 + if err != nil {
42 + fmt.Println(err)
43 + return
44 + }
45 + pprof.StartCPUProfile(ofi)
46 + defer ofi.Close()
47 + defer pprof.StopCPUProfile()
48 + }
49 }
50
190 - cc.node, err = localNode(cc.configDir, online)
191 - if err != nil {
192 - return
193 - }
51 + res := commands.Root.Call(req)
52
195 - cc.daemon, err = setupDaemon(cc.configDir, cc.node)
196 - if err != nil {
197 - return
198 - }
199 -
200 - return
201 -}
53 + if res.Error() != nil {
54 + fmt.Println(res.Error().Error())
55
203 -// setupDaemon sets up the daemon corresponding to given node.
204 -func setupDaemon(confdir string, node *core.IpfsNode) (*daemon.DaemonListener, error) {
205 - if node.Config.Addresses.API == "" {
206 - return nil, errors.New("no config.Addresses.API endpoint supplied")
207 - }
56 + if cmd.Help != "" && res.Error().Code == cmds.ErrClient {
57 + // TODO: convert from markdown to ANSI terminal format?
58 + fmt.Println(cmd.Help)
59 + }
60
209 - maddr, err := ma.NewMultiaddr(node.Config.Addresses.API)
210 - if err != nil {
211 - return nil, err
61 + os.Exit(1)
62 }
63
214 - dl, err := daemon.NewDaemonListener(node, maddr, confdir)
64 + _, err = io.Copy(os.Stdout, res)
65 if err != nil {
216 - return nil, err
66 + fmt.Println(err.Error())
67 }
218 - go dl.Listen()
219 - return dl, nil
68 }