@cryptotaxi247 / kubo / commits / d18902df2

cmds2: changed how the ctx.Node works

Juan Batiz-Benet committed Nov 12, 2014 at 22:37 UTC d18902df27d5b0e1c1b2e562a409b80185797897
17 files changed +222 -77
cmd/ipfs2/daemon.go
+14 -7
@@ -22,21 +22,28 @@ var daemonCmd = &cmds.Command{
22 }
23
24 func daemonFunc(req cmds.Request) (interface{}, error) {
25 - ctx := req.Context()
26 -
27 - lock, err := daemon.Lock(ctx.ConfigRoot)
25 + lock, err := daemon.Lock(req.Context().ConfigRoot)
26 if err != nil {
27 return nil, fmt.Errorf("Couldn't obtain lock. Is another daemon already running?")
28 }
29 defer lock.Close()
30
33 - node, err := core.NewIpfsNode(ctx.Config, true)
31 + cfg, err := req.Context().GetConfig()
32 + if err != nil {
33 + return nil, err
34 + }
35 +
36 + // setup function that constructs the context. we have to do it this way
37 + // to play along with how the Context works and thus not expose its internals
38 + req.Context().ConstructNode = func() (*core.IpfsNode, error) {
39 + return core.NewIpfsNode(cfg, true)
40 + }
41 + node, err := req.Context().GetNode()
42 if err != nil {
43 return nil, err
44 }
37 - ctx.Node = node
45
39 - addr, err := ma.NewMultiaddr(ctx.Config.Addresses.API)
46 + addr, err := ma.NewMultiaddr(cfg.Addresses.API)
47 if err != nil {
48 return nil, err
49 }
@@ -46,7 +53,7 @@ func daemonFunc(req cmds.Request) (interface{}, error) {
53 return nil, err
54 }
55
49 - cmdHandler := cmdsHttp.NewHandler(*ctx, commands.Root)
56 + cmdHandler := cmdsHttp.NewHandler(*req.Context(), commands.Root)
57 http.Handle(cmdsHttp.ApiPath+"/", cmdHandler)
58
59 ifpsHandler := &ipfsHandler{node}
cmd/ipfs2/main.go
+43 -35
@@ -166,13 +166,10 @@ func (i *cmdInvocation) Parse(args []string) error {
166 return err
167 }
168
169 - conf, err := getConfig(configPath)
170 - if err != nil {
171 - return err
172 - }
169 + // this sets up the function that will initialize the config lazily.
170 ctx := i.req.Context()
171 ctx.ConfigRoot = configPath
175 - ctx.Config = conf
172 + ctx.LoadConfig = loadConfig
173
174 // if no encoding was specified by user, default to plaintext encoding
175 // (if command doesn't support plaintext, use JSON instead)
@@ -202,51 +199,62 @@ func (i *cmdInvocation) requestedHelp() (short bool, long bool, err error) {
199 func callCommand(req cmds.Request, root *cmds.Command) (cmds.Response, error) {
200 var res cmds.Response
201
205 - // TODO explain what it means when root == Root
206 - // @mappum o/
207 - if root == Root {
208 - res = root.Call(req)
202 + local, found, err := req.Option("local").Bool()
203 + if err != nil {
204 + return nil, err
205 + }
206 + remote := !found || !local
207
210 - } else {
211 - local, found, err := req.Option("local").Bool()
208 + log.Info("Checking if daemon is running...")
209 + if remote && daemon.Locked(req.Context().ConfigRoot) {
210 +
211 + cfg, err := req.Context().GetConfig()
212 if err != nil {
213 return nil, err
214 }
215
216 - remote := !found || !local
216 + addr, err := ma.NewMultiaddr(cfg.Addresses.API)
217 + if err != nil {
218 + return nil, err
219 + }
220
218 - log.Info("Checking if daemon is running...")
219 - if remote && daemon.Locked(req.Context().ConfigRoot) {
220 - addr, err := ma.NewMultiaddr(req.Context().Config.Addresses.API)
221 - if err != nil {
222 - return nil, err
223 - }
221 + _, host, err := manet.DialArgs(addr)
222 + if err != nil {
223 + return nil, err
224 + }
225
225 - _, host, err := manet.DialArgs(addr)
226 - if err != nil {
227 - return nil, err
228 - }
226 + client := cmdsHttp.NewClient(host)
227
230 - client := cmdsHttp.NewClient(host)
228 + res, err = client.Send(req)
229 + if err != nil {
230 + return nil, err
231 + }
232
232 - res, err = client.Send(req)
233 - if err != nil {
234 - return nil, err
235 - }
233 + } else {
234 + log.Info("Executing command locally: daemon not running")
235
237 - } else {
238 - log.Info("Executing command locally: daemon not running")
239 - node, err := core.NewIpfsNode(req.Context().Config, false)
236 + // this sets up the function that will initialize the node
237 + // this is so that we can construct the node lazily.
238 + ctx := req.Context()
239 + ctx.ConstructNode = func() (*core.IpfsNode, error) {
240 + cfg, err := ctx.GetConfig()
241 if err != nil {
242 return nil, err
243 }
243 - defer node.Close()
244 - req.Context().Node = node
244 + return core.NewIpfsNode(cfg, false)
245 + }
246 +
247 + // Okay!!!!! NOW we can call the command.
248 + res = root.Call(req)
249
246 - res = root.Call(req)
250 + // let's not forget teardown. If a node was initialized, we must close it.
251 + // Note that this means the underlying req.Context().Node variable is exposed.
252 + // this is gross, and should be changed when we extract out the exec Context.
253 + node := req.Context().NodeWithoutConstructing()
254 + if node != nil {
255 + node.Close()
256 }
257 }
249 -
258 return res, nil
259 }
260
@@ -275,7 +283,7 @@ func getConfigRoot(req cmds.Request) (string, error) {
283 return configPath, nil
284 }
285
278 -func getConfig(path string) (*config.Config, error) {
286 +func loadConfig(path string) (*config.Config, error) {
287 configFile, err := config.Filename(path)
288 if err != nil {
289 return nil, err
cmd/ipfs2/tour.go
+20 -5
@@ -32,7 +32,11 @@ IPFS very quickly. To start, run:
32 Run: func(req cmds.Request) (interface{}, error) {
33
34 out := new(bytes.Buffer)
35 - cfg := req.Context().Config
35 + cfg, err := req.Context().GetConfig()
36 + if err != nil {
37 + return nil, err
38 + }
39 +
40 strs, err := internal.CastToStrings(req.Arguments())
41 if err != nil {
42 return nil, err
@@ -57,8 +61,11 @@ var cmdIpfsTourNext = &cmds.Command{
61
62 Run: func(req cmds.Request) (interface{}, error) {
63 var w bytes.Buffer
60 - cfg := req.Context().Config
64 path := req.Context().ConfigRoot
65 + cfg, err := req.Context().GetConfig()
66 + if err != nil {
67 + return nil, err
68 + }
69
70 topic := tour.NextTopic(tour.TopicID(cfg.Tour.Last))
71 if err := tourShow(&w, topic); err != nil {
@@ -84,10 +91,13 @@ var cmdIpfsTourRestart = &cmds.Command{
91
92 Run: func(req cmds.Request) (interface{}, error) {
93 path := req.Context().ConfigRoot
87 - cfg := req.Context().Config
94 + cfg, err := req.Context().GetConfig()
95 + if err != nil {
96 + return nil, err
97 + }
98
99 cfg.Tour.Last = ""
90 - err := writeConfig(path, cfg)
100 + err = writeConfig(path, cfg)
101 if err != nil {
102 return nil, err
103 }
@@ -99,8 +109,13 @@ var cmdIpfsTourList = &cmds.Command{
109 Description: "Show a list of IPFS Tour topics",
110
111 Run: func(req cmds.Request) (interface{}, error) {
112 + cfg, err := req.Context().GetConfig()
113 + if err != nil {
114 + return nil, err
115 + }
116 +
117 var w bytes.Buffer
103 - tourListCmd(&w, req.Context().Config)
118 + tourListCmd(&w, cfg)
119 w.WriteTo(os.Stdout) // TODO use res.SetOutput(output)
120 return nil, nil
121 },
commands/request.go
+38 -2
@@ -15,8 +15,44 @@ type optMap map[string]interface{}
15
16 type Context struct {
17 ConfigRoot string
18 - Config *config.Config
19 - Node *core.IpfsNode
18 +
19 + config *config.Config
20 + LoadConfig func(path string) (*config.Config, error)
21 +
22 + node *core.IpfsNode
23 + ConstructNode func() (*core.IpfsNode, error)
24 +}
25 +
26 +// GetConfig returns the config of the current Command exection
27 +// context. It may load it with the providied function.
28 +func (c *Context) GetConfig() (*config.Config, error) {
29 + var err error
30 + if c.config == nil {
31 + if c.LoadConfig == nil {
32 + panic("nil LoadConfig function")
33 + }
34 + c.config, err = c.LoadConfig(c.ConfigRoot)
35 + }
36 + return c.config, err
37 +}
38 +
39 +// GetNode returns the node of the current Command exection
40 +// context. It may construct it with the providied function.
41 +func (c *Context) GetNode() (*core.IpfsNode, error) {
42 + var err error
43 + if c.node == nil {
44 + if c.ConstructNode == nil {
45 + panic("nil ConstructNode function")
46 + }
47 + c.node, err = c.ConstructNode()
48 + }
49 + return c.node, err
50 +}
51 +
52 +// NodeWithoutConstructing returns the underlying node variable
53 +// so that clients may close it.
54 +func (c *Context) NodeWithoutConstructing() *core.IpfsNode {
55 + return c.node
56 }
57
58 // Request represents a call to a command from a consumer
core/commands2/add.go
+4 -1
@@ -43,7 +43,10 @@ remains to be implemented.
43 `,
44 Run: func(req cmds.Request) (interface{}, error) {
45 added := &AddOutput{}
46 - n := req.Context().Node
46 + n, err := req.Context().GetNode()
47 + if err != nil {
48 + return nil, err
49 + }
50
51 recursive, _, err := req.Option("r").Bool()
52 if err != nil {
core/commands2/block.go
+8 -2
@@ -40,7 +40,10 @@ It outputs to stdout, and <key> is a base58 encoded multihash.`,
40 cmds.StringArg("key", true, false, "The base58 multihash of an existing block to get"),
41 },
42 Run: func(req cmds.Request) (interface{}, error) {
43 - n := req.Context().Node
43 + n, err := req.Context().GetNode()
44 + if err != nil {
45 + return nil, err
46 + }
47
48 key, ok := req.Arguments()[0].(string)
49 if !ok {
@@ -76,7 +79,10 @@ It reads from stdin, and <key> is a base58 encoded multihash.`,
79 cmds.FileArg("data", true, false, "The data to be stored as an IPFS block"),
80 },
81 Run: func(req cmds.Request) (interface{}, error) {
79 - n := req.Context().Node
82 + n, err := req.Context().GetNode()
83 + if err != nil {
84 + return nil, err
85 + }
86
87 in, ok := req.Arguments()[0].(io.Reader)
88 if !ok {
core/commands2/bootstrap.go
+18 -3
@@ -54,7 +54,12 @@ in the bootstrap list).
54 return nil, err
55 }
56
57 - added, err := bootstrapAdd(filename, req.Context().Config, input)
57 + cfg, err := req.Context().GetConfig()
58 + if err != nil {
59 + return nil, err
60 + }
61 +
62 + added, err := bootstrapAdd(filename, cfg, input)
63 if err != nil {
64 return nil, err
65 }
@@ -94,7 +99,12 @@ var bootstrapRemoveCmd = &cmds.Command{
99 return nil, err
100 }
101
97 - removed, err := bootstrapRemove(filename, req.Context().Config, input)
102 + cfg, err := req.Context().GetConfig()
103 + if err != nil {
104 + return nil, err
105 + }
106 +
107 + removed, err := bootstrapRemove(filename, cfg, input)
108 if err != nil {
109 return nil, err
110 }
@@ -121,7 +131,12 @@ var bootstrapListCmd = &cmds.Command{
131 `,
132
133 Run: func(req cmds.Request) (interface{}, error) {
124 - peers := req.Context().Config.Bootstrap
134 + cfg, err := req.Context().GetConfig()
135 + if err != nil {
136 + return nil, err
137 + }
138 +
139 + peers := cfg.Bootstrap
140 return &BootstrapOutput{peers}, nil
141 },
142 Type: &BootstrapOutput{},
core/commands2/cat.go
+5 -1
@@ -19,7 +19,11 @@ it contains.
19 cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to be outputted"),
20 },
21 Run: func(req cmds.Request) (interface{}, error) {
22 - node := req.Context().Node
22 + node, err := req.Context().GetNode()
23 + if err != nil {
24 + return nil, err
25 + }
26 +
27 readers := make([]io.Reader, 0, len(req.Arguments()))
28
29 paths, err := internal.CastToStrings(req.Arguments())
core/commands2/diag.go
+4 -1
@@ -44,7 +44,10 @@ connected peers and latencies between them.
44 `,
45
46 Run: func(req cmds.Request) (interface{}, error) {
47 - n := req.Context().Node
47 + n, err := req.Context().GetNode()
48 + if err != nil {
49 + return nil, err
50 + }
51
52 if !n.OnlineMode() {
53 return nil, errNotOnline
core/commands2/ls.go
+4 -1
@@ -34,7 +34,10 @@ it contains, with the following format:
34 cmds.StringArg("ipfs-path", false, true, "The path to the IPFS object(s) to list links from"),
35 },
36 Run: func(req cmds.Request) (interface{}, error) {
37 - node := req.Context().Node
37 + node, err := req.Context().GetNode()
38 + if err != nil {
39 + return nil, err
40 + }
41
42 paths, err := internal.CastToStrings(req.Arguments())
43 if err != nil {
core/commands2/mount_unix.go
+15 -7
@@ -32,10 +32,18 @@ not be listable, as it is virtual. Accessing known paths directly.
32 cmds.StringOption("n", "The path where IPNS should be mounted\n(default is '/ipns')"),
33 },
34 Run: func(req cmds.Request) (interface{}, error) {
35 - ctx := req.Context()
35 + cfg, err := req.Context().GetConfig()
36 + if err != nil {
37 + return nil, err
38 + }
39 +
40 + node, err := req.Context().GetNode()
41 + if err != nil {
42 + return nil, err
43 + }
44
45 // error if we aren't running node in online mode
38 - if ctx.Node.Network == nil {
46 + if node.Network == nil {
47 return nil, errNotOnline
48 }
49
@@ -48,9 +56,9 @@ not be listable, as it is virtual. Accessing known paths directly.
56 return nil, err
57 }
58 if !found {
51 - fsdir = ctx.Config.Mounts.IPFS // use default value
59 + fsdir = cfg.Mounts.IPFS // use default value
60 }
53 - fsdone := mountIpfs(ctx.Node, fsdir)
61 + fsdone := mountIpfs(node, fsdir)
62
63 // get default mount points
64 nsdir, found, err := req.Option("n").String()
@@ -58,10 +66,10 @@ not be listable, as it is virtual. Accessing known paths directly.
66 return nil, err
67 }
68 if !found {
61 - nsdir = ctx.Config.Mounts.IPNS // NB: be sure to not redeclare!
69 + nsdir = cfg.Mounts.IPNS // NB: be sure to not redeclare!
70 }
71
64 - nsdone := mountIpns(ctx.Node, nsdir, fsdir)
72 + nsdone := mountIpns(node, nsdir, fsdir)
73
74 // wait until mounts return an error (or timeout if successful)
75 select {
@@ -72,7 +80,7 @@ not be listable, as it is virtual. Accessing known paths directly.
80
81 // mounted successfully, we timed out with no errors
82 case <-time.After(mountTimeout):
75 - output := ctx.Config.Mounts
83 + output := cfg.Mounts
84 return &output, nil
85 }
86 },
core/commands2/object.go
+16 -4
@@ -48,7 +48,10 @@ output is the raw data of the object.
48 cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format"),
49 },
50 Run: func(req cmds.Request) (interface{}, error) {
51 - n := req.Context().Node
51 + n, err := req.Context().GetNode()
52 + if err != nil {
53 + return nil, err
54 + }
55
56 key, ok := req.Arguments()[0].(string)
57 if !ok {
@@ -68,7 +71,10 @@ It outputs to stdout, and <key> is a base58 encoded multihash.`,
71 cmds.StringArg("key", true, false, "Key of the object to retrieve, in base58-encoded multihash format"),
72 },
73 Run: func(req cmds.Request) (interface{}, error) {
71 - n := req.Context().Node
74 + n, err := req.Context().GetNode()
75 + if err != nil {
76 + return nil, err
77 + }
78
79 key, ok := req.Arguments()[0].(string)
80 if !ok {
@@ -96,7 +102,10 @@ This command outputs data in the following encodings:
102 cmds.StringArg("key", true, false, "Key of the object to retrieve\n(in base58-encoded multihash format)"),
103 },
104 Run: func(req cmds.Request) (interface{}, error) {
99 - n := req.Context().Node
105 + n, err := req.Context().GetNode()
106 + if err != nil {
107 + return nil, err
108 + }
109
110 key, ok := req.Arguments()[0].(string)
111 if !ok {
@@ -148,7 +157,10 @@ Data should be in the format specified by <encoding>.
157 cmds.StringArg("encoding", true, false, "Encoding type of <data>, either \"protobuf\" or \"json\""),
158 },
159 Run: func(req cmds.Request) (interface{}, error) {
151 - n := req.Context().Node
160 + n, err := req.Context().GetNode()
161 + if err != nil {
162 + return nil, err
163 + }
164
165 input, ok := req.Arguments()[0].(io.Reader)
166 if !ok {
core/commands2/pin.go
+8 -2
@@ -31,7 +31,10 @@ on disk.
31 cmds.BoolOption("recursive", "r", "Recursively pin the object linked to by the specified object(s)"),
32 },
33 Run: func(req cmds.Request) (interface{}, error) {
34 - n := req.Context().Node
34 + n, err := req.Context().GetNode()
35 + if err != nil {
36 + return nil, err
37 + }
38
39 // set recursive flag
40 recursive, found, err := req.Option("recursive").Bool()
@@ -70,7 +73,10 @@ collected if needed.
73 cmds.BoolOption("recursive", "r", "Recursively unpin the object linked to by the specified object(s)"),
74 },
75 Run: func(req cmds.Request) (interface{}, error) {
73 - n := req.Context().Node
76 + n, err := req.Context().GetNode()
77 + if err != nil {
78 + return nil, err
79 + }
80
81 // set recursive flag
82 recursive, found, err := req.Option("recursive").Bool()
core/commands2/publish.go
+4 -1
@@ -39,8 +39,11 @@ Publish a <ref> to another public key:
39 },
40 Run: func(req cmds.Request) (interface{}, error) {
41 log.Debug("Begin Publish")
42 + n, err := req.Context().GetNode()
43 + if err != nil {
44 + return nil, err
45 + }
46
43 - n := req.Context().Node
47 args := req.Arguments()
48
49 if n.Network == nil {
core/commands2/refs.go
+4 -1
@@ -32,7 +32,10 @@ Note: list all refs recursively with -r.`,
32 cmds.BoolOption("recursive", "r", "Recursively list links of child nodes"),
33 },
34 Run: func(req cmds.Request) (interface{}, error) {
35 - n := req.Context().Node
35 + n, err := req.Context().GetNode()
36 + if err != nil {
37 + return nil, err
38 + }
39
40 unique, found, err := req.Option("unique").Bool()
41 if err != nil {
core/commands2/resolve.go
+5 -1
@@ -33,7 +33,11 @@ Resolve te value of another name:
33 },
34 Run: func(req cmds.Request) (interface{}, error) {
35
36 - n := req.Context().Node
36 + n, err := req.Context().GetNode()
37 + if err != nil {
38 + return nil, err
39 + }
40 +
41 var name string
42
43 if n.Network == nil {
core/commands2/update.go
+12 -3
@@ -20,7 +20,10 @@ var updateCmd = &cmds.Command{
20 `,
21
22 Run: func(req cmds.Request) (interface{}, error) {
23 - n := req.Context().Node
23 + n, err := req.Context().GetNode()
24 + if err != nil {
25 + return nil, err
26 + }
27 return updateApply(n)
28 },
29 Type: &UpdateOutput{},
@@ -51,7 +54,10 @@ Nothing will be downloaded or installed.
54 `,
55
56 Run: func(req cmds.Request) (interface{}, error) {
54 - n := req.Context().Node
57 + n, err := req.Context().GetNode()
58 + if err != nil {
59 + return nil, err
60 + }
61 return updateCheck(n)
62 },
63 Type: &UpdateOutput{},
@@ -76,7 +82,10 @@ var updateLogCmd = &cmds.Command{
82 `,
83
84 Run: func(req cmds.Request) (interface{}, error) {
79 - n := req.Context().Node
85 + n, err := req.Context().GetNode()
86 + if err != nil {
87 + return nil, err
88 + }
89 return updateLog(n)
90 },
91 }