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
}