copy to old location
Brian Tiger Chow committed
Oct 28, 2014 at 23:48 UTC
d1fa4bd9b5a3a9ec8620fb67fe052bec3bd314cc
29 files changed
+1925
cmd/ipfs/.gitignore
new
+1
@@ -0,0 +1 @@
1
+./ipfs
cmd/ipfs/Makefile
new
+7
@@ -0,0 +1,7 @@
1
+all: install
2
+
3
+build:
4
+ go build
5
+
6
+install: build
7
+ go install
cmd/ipfs/README.md
new
+29
@@ -0,0 +1,29 @@
1
+# go-ipfs/cmd/ipfs
2
+
3
+This is the ipfs commandline tool. For now, it's the main entry point to using IPFS. Use it.
4
+
5
+```
6
+> go build
7
+> go install
8
+> ipfs
9
+ipfs - global versioned p2p merkledag file system
10
+
11
+Basic commands:
12
+
13
+ add <path> Add an object to ipfs.
14
+ cat <ref> Show ipfs object data.
15
+ ls <ref> List links from an object.
16
+ refs <ref> List link hashes from an object.
17
+
18
+Tool commands:
19
+
20
+ config Manage configuration.
21
+ version Show ipfs version information.
22
+ commands List all available commands.
23
+
24
+Advanced Commands:
25
+
26
+ mount Mount an ipfs read-only mountpoint.
27
+
28
+Use "ipfs help <command>" for more information about a command.
29
+```
cmd/ipfs/add.go
new
+39
@@ -0,0 +1,39 @@
1
+package main
2
+
3
+import (
4
+ "fmt"
5
+ "path/filepath"
6
+
7
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
8
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
9
+ "github.com/jbenet/go-ipfs/core/commands"
10
+)
11
+
12
+// Error indicating the max depth has been exceded.
13
+var ErrDepthLimitExceeded = fmt.Errorf("depth limit exceeded")
14
+
15
+var cmdIpfsAdd = &commander.Command{
16
+ UsageLine: "add",
17
+ Short: "Add an object to ipfs.",
18
+ Long: `ipfs add <path>... - Add objects to ipfs.
19
+
20
+ Adds contents of <path> to ipfs. Use -r to add directories.
21
+ Note that directories are added recursively, to form the ipfs
22
+ MerkleDAG. A smarter partial add with a staging area (like git)
23
+ remains to be implemented.
24
+`,
25
+ Run: addCmd,
26
+ Flag: *flag.NewFlagSet("ipfs-add", flag.ExitOnError),
27
+}
28
+
29
+func init() {
30
+ cmdIpfsAdd.Flag.Bool("r", false, "add objects recursively")
31
+}
32
+
33
+var addCmd = makeCommand(command{
34
+ name: "add",
35
+ args: 1,
36
+ flags: []string{"r"},
37
+ cmdFn: commands.Add,
38
+ argFilter: filepath.Abs,
39
+})
cmd/ipfs/block.go
new
+58
@@ -0,0 +1,58 @@
1
+package main
2
+
3
+import (
4
+ flag "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5
+ commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
6
+ "github.com/jbenet/go-ipfs/core/commands"
7
+)
8
+
9
+var cmdIpfsBlock = &commander.Command{
10
+ UsageLine: "block",
11
+ Short: "manipulate raw ipfs blocks",
12
+ Long: `ipfs block - manipulate raw ipfs blocks
13
+
14
+ ipfs block get <key> - get and output block named by <key>
15
+ ipfs block put - store stdin as a block, outputs <key>
16
+
17
+ipfs block is a plumbing command used to manipulate raw ipfs blocks.
18
+Reads from stdin or writes to stdout, and <key> is a base58 encoded
19
+multihash.`,
20
+ // Run: blockGetCmd,
21
+ Subcommands: []*commander.Command{
22
+ cmdIpfsBlockGet,
23
+ cmdIpfsBlockPut,
24
+ },
25
+ Flag: *flag.NewFlagSet("ipfs-block", flag.ExitOnError),
26
+}
27
+
28
+var cmdIpfsBlockGet = &commander.Command{
29
+ UsageLine: "get <key>",
30
+ Short: "get and output block named by <key>",
31
+ Long: `ipfs get <key> - get and output block named by <key>
32
+
33
+ipfs block get is a plumbing command for retreiving raw ipfs blocks.
34
+It outputs to stdout, and <key> is a base58 encoded multihash.`,
35
+ Run: makeCommand(command{
36
+ name: "blockGet",
37
+ args: 1,
38
+ flags: nil,
39
+ online: true,
40
+ cmdFn: commands.BlockGet,
41
+ }),
42
+}
43
+
44
+var cmdIpfsBlockPut = &commander.Command{
45
+ UsageLine: "put",
46
+ Short: "store stdin as a block, outputs <key>",
47
+ Long: `ipfs put - store stdin as a block, outputs <key>
48
+
49
+ipfs block put is a plumbing command for storing raw ipfs blocks.
50
+It reads from stding, and <key> is a base58 encoded multihash.`,
51
+ Run: makeCommand(command{
52
+ name: "blockPut",
53
+ args: 0,
54
+ flags: nil,
55
+ online: true,
56
+ cmdFn: commands.BlockPut,
57
+ }),
58
+}
cmd/ipfs/bootstrap.go
new
+236
@@ -0,0 +1,236 @@
1
+package main
2
+
3
+import (
4
+ "errors"
5
+ "strings"
6
+
7
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
8
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
9
+ ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
10
+ mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
11
+
12
+ config "github.com/jbenet/go-ipfs/config"
13
+ peer "github.com/jbenet/go-ipfs/peer"
14
+ u "github.com/jbenet/go-ipfs/util"
15
+)
16
+
17
+var cmdIpfsBootstrap = &commander.Command{
18
+ UsageLine: "bootstrap",
19
+ Short: "Show a list of bootstrapped addresses.",
20
+ Long: `ipfs bootstrap - show, or manipulate bootstrap node addresses
21
+
22
+Running 'ipfs bootstrap' with no arguments will run 'ipfs bootstrap list'.
23
+
24
+Commands:
25
+
26
+ list Show the boostrap list.
27
+ add <address> Add a node's address to the bootstrap list.
28
+ remove <address> Remove an address from the bootstrap list.
29
+
30
+` + bootstrapSecurityWarning,
31
+ Run: bootstrapListCmd,
32
+ Subcommands: []*commander.Command{
33
+ cmdIpfsBootstrapRemove,
34
+ cmdIpfsBootstrapAdd,
35
+ cmdIpfsBootstrapList,
36
+ },
37
+ Flag: *flag.NewFlagSet("ipfs-bootstrap", flag.ExitOnError),
38
+}
39
+
40
+var cmdIpfsBootstrapRemove = &commander.Command{
41
+ UsageLine: "remove <address | peerid>",
42
+ Short: "Remove addresses from the bootstrap list.",
43
+ Long: `ipfs bootstrap remove - remove addresses from the bootstrap list
44
+` + bootstrapSecurityWarning,
45
+ Run: bootstrapRemoveCmd,
46
+ Flag: *flag.NewFlagSet("ipfs-bootstrap-remove", flag.ExitOnError),
47
+}
48
+
49
+var cmdIpfsBootstrapAdd = &commander.Command{
50
+ UsageLine: "add <address | peerid>",
51
+ Short: "Add addresses to the bootstrap list.",
52
+ Long: `ipfs bootstrap add - add addresses to the bootstrap list
53
+` + bootstrapSecurityWarning,
54
+ Run: bootstrapAddCmd,
55
+ Flag: *flag.NewFlagSet("ipfs-bootstrap-add", flag.ExitOnError),
56
+}
57
+
58
+var cmdIpfsBootstrapList = &commander.Command{
59
+ UsageLine: "list",
60
+ Short: "Show addresses in the bootstrap list.",
61
+ Run: bootstrapListCmd,
62
+ Flag: *flag.NewFlagSet("ipfs-bootstrap-list", flag.ExitOnError),
63
+}
64
+
65
+func bootstrapRemoveCmd(c *commander.Command, inp []string) error {
66
+
67
+ if len(inp) == 0 {
68
+ return errors.New("remove: no address or peerid specified")
69
+ }
70
+
71
+ toRemove, err := bootstrapInputToPeers(inp)
72
+ if err != nil {
73
+ return err
74
+ }
75
+
76
+ cfg, err := getConfig(c)
77
+ if err != nil {
78
+ return err
79
+ }
80
+
81
+ keep := []*config.BootstrapPeer{}
82
+ remove := []*config.BootstrapPeer{}
83
+
84
+ // function to filer what to keep
85
+ shouldKeep := func(bp *config.BootstrapPeer) bool {
86
+ for _, skipBP := range toRemove {
87
+
88
+ // IDs must match to skip.
89
+ if bp.PeerID != skipBP.PeerID {
90
+ continue
91
+ }
92
+
93
+ // if Addresses match, or skipBP has no addr (wildcard)
94
+ if skipBP.Address == bp.Address || skipBP.Address == "" {
95
+ return false
96
+ }
97
+ }
98
+ return true
99
+ }
100
+
101
+ // filter all the existing peers
102
+ for _, currBP := range cfg.Bootstrap {
103
+ if shouldKeep(currBP) {
104
+ keep = append(keep, currBP)
105
+ } else {
106
+ remove = append(remove, currBP)
107
+ }
108
+ }
109
+
110
+ // if didn't remove anyone, bail.
111
+ if len(keep) == len(cfg.Bootstrap) {
112
+ return errors.New("remove: peer given did not match any in list")
113
+ }
114
+
115
+ // write new config
116
+ cfg.Bootstrap = keep
117
+ if err := writeConfig(c, cfg); err != nil {
118
+ return err
119
+ }
120
+
121
+ for _, bp := range remove {
122
+ u.POut("removed %s\n", bp)
123
+ }
124
+ return nil
125
+}
126
+
127
+func bootstrapAddCmd(c *commander.Command, inp []string) error {
128
+
129
+ if len(inp) == 0 {
130
+ return errors.New("add: no address specified")
131
+ }
132
+
133
+ toAdd, err := bootstrapInputToPeers(inp)
134
+ if err != nil {
135
+ return err
136
+ }
137
+
138
+ cfg, err := getConfig(c)
139
+ if err != nil {
140
+ return err
141
+ }
142
+
143
+ // function to check whether a peer is already in the list.
144
+ combine := func(lists ...[]*config.BootstrapPeer) []*config.BootstrapPeer {
145
+
146
+ set := map[string]struct{}{}
147
+ final := []*config.BootstrapPeer{}
148
+
149
+ for _, list := range lists {
150
+ for _, peer := range list {
151
+ // if already in the set, continue
152
+ _, found := set[peer.String()]
153
+ if found {
154
+ continue
155
+ }
156
+
157
+ set[peer.String()] = struct{}{}
158
+ final = append(final, peer)
159
+ }
160
+ }
161
+ return final
162
+ }
163
+
164
+ // combine both lists, removing dups.
165
+ cfg.Bootstrap = combine(cfg.Bootstrap, toAdd)
166
+ if err := writeConfig(c, cfg); err != nil {
167
+ return err
168
+ }
169
+
170
+ for _, bp := range toAdd {
171
+ u.POut("added %s\n", bp)
172
+ }
173
+ return nil
174
+}
175
+
176
+func bootstrapListCmd(c *commander.Command, inp []string) error {
177
+
178
+ cfg, err := getConfig(c)
179
+ if err != nil {
180
+ return err
181
+ }
182
+
183
+ for _, bp := range cfg.Bootstrap {
184
+ u.POut("%s\n", bp)
185
+ }
186
+
187
+ return nil
188
+}
189
+
190
+func bootstrapInputToPeers(input []string) ([]*config.BootstrapPeer, error) {
191
+ split := func(addr string) (string, string) {
192
+ idx := strings.LastIndex(addr, "/")
193
+ if idx == -1 {
194
+ return "", addr
195
+ }
196
+ return addr[:idx], addr[idx+1:]
197
+ }
198
+
199
+ peers := []*config.BootstrapPeer{}
200
+ for _, addr := range input {
201
+ addrS, peeridS := split(addr)
202
+
203
+ // make sure addrS parses as a multiaddr.
204
+ if len(addrS) > 0 {
205
+ maddr, err := ma.NewMultiaddr(addrS)
206
+ if err != nil {
207
+ return nil, err
208
+ }
209
+
210
+ addrS = maddr.String()
211
+ }
212
+
213
+ // make sure idS parses as a peer.ID
214
+ peerid, err := mh.FromB58String(peeridS)
215
+ if err != nil {
216
+ return nil, err
217
+ }
218
+
219
+ // construct config entry
220
+ peers = append(peers, &config.BootstrapPeer{
221
+ Address: addrS,
222
+ PeerID: peer.ID(peerid).Pretty(),
223
+ })
224
+ }
225
+ return peers, nil
226
+}
227
+
228
+const bootstrapSecurityWarning = `
229
+SECURITY WARNING:
230
+
231
+The bootstrap command manipulates the "bootstrap list", which contains
232
+the addresses of bootstrap nodes. These are the *trusted peers* from
233
+which to learn about other peers in the network. Only edit this list
234
+if you understand the risks of adding or removing nodes from this list.
235
+
236
+`
cmd/ipfs/cat.go
new
+26
@@ -0,0 +1,26 @@
1
+package main
2
+
3
+import (
4
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
6
+ "github.com/jbenet/go-ipfs/core/commands"
7
+)
8
+
9
+var cmdIpfsCat = &commander.Command{
10
+ UsageLine: "cat",
11
+ Short: "Show ipfs object data.",
12
+ Long: `ipfs cat <ipfs-path> - Show ipfs object data.
13
+
14
+ Retrieves the object named by <ipfs-path> and displays the Data
15
+ it contains.
16
+`,
17
+ Run: catCmd,
18
+ Flag: *flag.NewFlagSet("ipfs-cat", flag.ExitOnError),
19
+}
20
+
21
+var catCmd = makeCommand(command{
22
+ name: "cat",
23
+ args: 1,
24
+ flags: nil,
25
+ cmdFn: commands.Cat,
26
+})
cmd/ipfs/commands.go
new
+74
@@ -0,0 +1,74 @@
1
+package main
2
+
3
+import (
4
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
5
+ u "github.com/jbenet/go-ipfs/util"
6
+ "strings"
7
+ "time"
8
+)
9
+
10
+var cmdIpfsCommands = &commander.Command{
11
+ UsageLine: "commands",
12
+ Short: "List all available commands.",
13
+ Long: `ipfs commands - List all available commands.
14
+
15
+ Lists all available commands (and sub-commands) and exits.
16
+ `,
17
+ Run: commandsCmd,
18
+ Subcommands: []*commander.Command{
19
+ cmdIpfsCommandsHelp,
20
+ },
21
+}
22
+
23
+func commandsCmd(c *commander.Command, args []string) error {
24
+ var listCmds func(c *commander.Command)
25
+ listCmds = func(c *commander.Command) {
26
+ u.POut("%s\n", c.FullSpacedName())
27
+ for _, sc := range c.Subcommands {
28
+ listCmds(sc)
29
+ }
30
+ }
31
+
32
+ listCmds(c.Parent)
33
+ return nil
34
+}
35
+
36
+var cmdIpfsCommandsHelp = &commander.Command{
37
+ UsageLine: "help",
38
+ Short: "List all available commands' help pages.",
39
+ Long: `ipfs commands help - List all available commands's help pages.
40
+
41
+ Shows the pages of all available commands (and sub-commands) and exits.
42
+ Outputs a markdown document.
43
+ `,
44
+ Run: commandsHelpCmd,
45
+}
46
+
47
+func commandsHelpCmd(c *commander.Command, args []string) error {
48
+ u.POut(referenceHeaderMsg)
49
+ u.POut("Generated on %s.\n\n", time.Now().UTC().Format("2006-01-02"))
50
+
51
+ var printCmds func(*commander.Command, int)
52
+ printCmds = func(c *commander.Command, level int) {
53
+ u.POut("%s ", strings.Repeat("#", level))
54
+ u.POut("%s\n\n", c.FullSpacedName())
55
+ u.POut("```\n")
56
+ u.POut("%s\n", c.Long)
57
+ u.POut("```\n\n")
58
+
59
+ for _, sc := range c.Subcommands {
60
+ printCmds(sc, level+1)
61
+ }
62
+ }
63
+
64
+ printCmds(c.Parent.Parent, 1)
65
+ return nil
66
+}
67
+
68
+const referenceHeaderMsg = `
69
+# ipfs command reference
70
+
71
+This document lists every ipfs command (including subcommands), along with
72
+its help page. It can be viewed by running 'ipfs commands help'.
73
+
74
+`
cmd/ipfs/config.go
new
+143
@@ -0,0 +1,143 @@
1
+package main
2
+
3
+import (
4
+ "errors"
5
+ "fmt"
6
+ "io"
7
+ "os"
8
+ "os/exec"
9
+
10
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
11
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
12
+ config "github.com/jbenet/go-ipfs/config"
13
+ u "github.com/jbenet/go-ipfs/util"
14
+)
15
+
16
+var cmdIpfsConfig = &commander.Command{
17
+ UsageLine: "config",
18
+ Short: "Get/Set ipfs config values",
19
+ Long: `ipfs config [<key>] [<value>] - Get/Set ipfs config values.
20
+
21
+ ipfs config <key> - Get value of <key>
22
+ ipfs config <key> <value> - Set value of <key> to <value>
23
+ ipfs config --show - Show config file
24
+ ipfs config --edit - Edit config file in $EDITOR
25
+
26
+Examples:
27
+
28
+ Get the value of the 'datastore.path' key:
29
+
30
+ ipfs config datastore.path
31
+
32
+ Set the value of the 'datastore.path' key:
33
+
34
+ ipfs config datastore.path ~/.go-ipfs/datastore
35
+
36
+`,
37
+ Run: configCmd,
38
+ Flag: *flag.NewFlagSet("ipfs-config", flag.ExitOnError),
39
+}
40
+
41
+func init() {
42
+ cmdIpfsConfig.Flag.Bool("edit", false, "Edit config file in $EDITOR")
43
+ cmdIpfsConfig.Flag.Bool("show", false, "Show config file")
44
+}
45
+
46
+func configCmd(c *commander.Command, inp []string) error {
47
+
48
+ confdir, err := getConfigDir(c.Parent)
49
+ if err != nil {
50
+ return err
51
+ }
52
+
53
+ filename, err := config.Filename(confdir)
54
+ if err != nil {
55
+ return err
56
+ }
57
+
58
+ // if editing, open the editor
59
+ if c.Flag.Lookup("edit").Value.Get().(bool) {
60
+ return configEditor(filename)
61
+ }
62
+
63
+ // if showing, cat the file
64
+ if c.Flag.Lookup("show").Value.Get().(bool) {
65
+ return configCat(filename)
66
+ }
67
+
68
+ if len(inp) == 0 {
69
+ // "ipfs config" run without parameters
70
+ u.POut(c.Long)
71
+ return nil
72
+ }
73
+
74
+ // Getter (1 param)
75
+ if len(inp) == 1 {
76
+ value, err := config.ReadConfigKey(filename, inp[0])
77
+ if err != nil {
78
+ return fmt.Errorf("Failed to get config value: %s", err)
79
+ }
80
+
81
+ strval, ok := value.(string)
82
+ if ok {
83
+ u.POut("%s\n", strval)
84
+ return nil
85
+ }
86
+
87
+ if err := config.Encode(os.Stdout, value); err != nil {
88
+ return fmt.Errorf("Failed to encode config value: %s", err)
89
+ }
90
+ u.POut("\n")
91
+ return nil
92
+ }
93
+
94
+ // Setter (>1 params)
95
+ err = config.WriteConfigKey(filename, inp[0], inp[1])
96
+ if err != nil {
97
+ return fmt.Errorf("Failed to set config value: %s", err)
98
+ }
99
+
100
+ return nil
101
+}
102
+
103
+func configCat(filename string) error {
104
+
105
+ file, err := os.Open(filename)
106
+ if err != nil {
107
+ return err
108
+ }
109
+ defer file.Close()
110
+
111
+ if _, err = io.Copy(os.Stdout, file); err != nil {
112
+ return err
113
+ }
114
+ u.POut("\n")
115
+ return nil
116
+}
117
+
118
+func configEditor(filename string) error {
119
+
120
+ editor := os.Getenv("EDITOR")
121
+ if editor == "" {
122
+ return errors.New("ENV variable $EDITOR not set")
123
+ }
124
+
125
+ cmd := exec.Command("sh", "-c", editor+" "+filename)
126
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
127
+ return cmd.Run()
128
+}
129
+
130
+func writeConfig(c *commander.Command, cfg *config.Config) error {
131
+
132
+ confdir, err := getConfigDir(c)
133
+ if err != nil {
134
+ return err
135
+ }
136
+
137
+ filename, err := config.Filename(confdir)
138
+ if err != nil {
139
+ return err
140
+ }
141
+
142
+ return config.WriteConfigFile(filename, cfg)
143
+}
cmd/ipfs/diag.go
new
+32
@@ -0,0 +1,32 @@
1
+package main
2
+
3
+import (
4
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5
+
6
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
7
+ "github.com/jbenet/go-ipfs/core/commands"
8
+)
9
+
10
+var cmdIpfsDiag = &commander.Command{
11
+ UsageLine: "net-diag",
12
+ Short: "Generate a diagnostics report",
13
+ Long: `ipfs net-diag - Generate a diagnostics report.
14
+
15
+ Sends out a message to each node in the network recursively
16
+ requesting a listing of data about them including number of
17
+ connected peers and latencies between them.
18
+`,
19
+ Run: diagCmd,
20
+ Flag: *flag.NewFlagSet("ipfs-net-diag", flag.ExitOnError),
21
+}
22
+
23
+func init() {
24
+ cmdIpfsDiag.Flag.Bool("raw", false, "print raw json output")
25
+}
26
+
27
+var diagCmd = makeCommand(command{
28
+ name: "diag",
29
+ args: 0,
30
+ flags: []string{"raw"},
31
+ cmdFn: commands.Diag,
32
+})
cmd/ipfs/equinox.yaml
new
+6
@@ -0,0 +1,6 @@
1
+---
2
+equinox-account: CHANGEME
3
+equinox-secret: CHANGEME
4
+equinox-app: CHANGEME
5
+channel: stable
6
+private-key: equinox-priv
cmd/ipfs/gen.go
new
+72
@@ -0,0 +1,72 @@
1
+package main
2
+
3
+import (
4
+ "fmt"
5
+ "os"
6
+
7
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
8
+ "github.com/jbenet/go-ipfs/core/commands"
9
+ "github.com/jbenet/go-ipfs/daemon"
10
+ u "github.com/jbenet/go-ipfs/util"
11
+)
12
+
13
+// command is the descriptor of an ipfs daemon command.
14
+// Used with makeCommand to proxy over commands via the daemon.
15
+type command struct {
16
+ name string
17
+ args int
18
+ flags []string
19
+ online bool
20
+ cmdFn commands.CmdFunc
21
+ argFilter func(string) (string, error)
22
+}
23
+
24
+// commanderFunc is a function that can be passed into the Commander library as
25
+// a command handler. Defined here because commander lacks this definition.
26
+type commanderFunc func(*commander.Command, []string) error
27
+
28
+// makeCommand Wraps a commands.CmdFunc so that it may be safely run by the
29
+// commander library
30
+func makeCommand(cmdDesc command) commanderFunc {
31
+ return func(c *commander.Command, inp []string) error {
32
+ if len(inp) < cmdDesc.args {
33
+ u.POut(c.Long)
34
+ return nil
35
+ }
36
+ confdir, err := getConfigDir(c)
37
+ if err != nil {
38
+ return err
39
+ }
40
+
41
+ cmd := daemon.NewCommand()
42
+ cmd.Command = cmdDesc.name
43
+ if cmdDesc.argFilter != nil {
44
+ for _, a := range inp {
45
+ s, err := cmdDesc.argFilter(a)
46
+ if err != nil {
47
+ return err
48
+ }
49
+ cmd.Args = append(cmd.Args, s)
50
+ }
51
+ } else {
52
+ cmd.Args = inp
53
+ }
54
+
55
+ for _, a := range cmdDesc.flags {
56
+ cmd.Opts[a] = c.Flag.Lookup(a).Value.Get()
57
+ }
58
+
59
+ err = daemon.SendCommand(cmd, confdir)
60
+ if err != nil {
61
+ log.Info("Executing command locally: %s", err)
62
+ // Do locally
63
+ n, err := localNode(confdir, cmdDesc.online)
64
+ if err != nil {
65
+ return fmt.Errorf("Local node creation failed: %v", err)
66
+ }
67
+
68
+ return cmdDesc.cmdFn(n, cmd.Args, cmd.Opts, os.Stdout)
69
+ }
70
+ return nil
71
+ }
72
+}
cmd/ipfs/init.go
new
+150
@@ -0,0 +1,150 @@
1
+package main
2
+
3
+import (
4
+ "encoding/base64"
5
+ "errors"
6
+ "os"
7
+ "path/filepath"
8
+
9
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
10
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
11
+ config "github.com/jbenet/go-ipfs/config"
12
+ ci "github.com/jbenet/go-ipfs/crypto"
13
+ peer "github.com/jbenet/go-ipfs/peer"
14
+ updates "github.com/jbenet/go-ipfs/updates"
15
+ u "github.com/jbenet/go-ipfs/util"
16
+)
17
+
18
+var cmdIpfsInit = &commander.Command{
19
+ UsageLine: "init",
20
+ Short: "Initialize ipfs local configuration",
21
+ Long: `ipfs init
22
+
23
+ Initializes ipfs configuration files and generates a
24
+ new keypair.
25
+`,
26
+ Run: initCmd,
27
+ Flag: *flag.NewFlagSet("ipfs-init", flag.ExitOnError),
28
+}
29
+
30
+func init() {
31
+ cmdIpfsInit.Flag.Int("b", 4096, "number of bits for keypair")
32
+ cmdIpfsInit.Flag.String("p", "", "passphrase for encrypting keys")
33
+ cmdIpfsInit.Flag.Bool("f", false, "force overwrite of existing config")
34
+ cmdIpfsInit.Flag.String("d", "", "Change default datastore location")
35
+}
36
+
37
+func initCmd(c *commander.Command, inp []string) error {
38
+ configpath, err := getConfigDir(c.Parent)
39
+ if err != nil {
40
+ return err
41
+ }
42
+
43
+ u.POut("initializing ipfs node at %s\n", configpath)
44
+ filename, err := config.Filename(configpath)
45
+ if err != nil {
46
+ return errors.New("Couldn't get home directory path")
47
+ }
48
+
49
+ dspath, ok := c.Flag.Lookup("d").Value.Get().(string)
50
+ if !ok {
51
+ return errors.New("failed to parse datastore flag")
52
+ }
53
+
54
+ fi, err := os.Lstat(filename)
55
+ force, ok := c.Flag.Lookup("f").Value.Get().(bool)
56
+ if !ok {
57
+ return errors.New("failed to parse force flag")
58
+ }
59
+ if fi != nil || (err != nil && !os.IsNotExist(err)) {
60
+ if !force {
61
+ return errors.New("ipfs configuration file already exists!\nReinitializing would overwrite your keys.\n(use -f to force overwrite)")
62
+ }
63
+ }
64
+ cfg := new(config.Config)
65
+
66
+ cfg.Datastore = config.Datastore{}
67
+ if len(dspath) == 0 {
68
+ dspath, err = config.DataStorePath("")
69
+ if err != nil {
70
+ return err
71
+ }
72
+ }
73
+ cfg.Datastore.Path = dspath
74
+ cfg.Datastore.Type = "leveldb"
75
+
76
+ // Construct the data store if missing
77
+ if err := os.MkdirAll(dspath, os.ModePerm); err != nil {
78
+ return err
79
+ }
80
+
81
+ // Check the directory is writeable
82
+ if f, err := os.Create(filepath.Join(dspath, "._check_writeable")); err == nil {
83
+ os.Remove(f.Name())
84
+ } else {
85
+ return errors.New("Datastore '" + dspath + "' is not writeable")
86
+ }
87
+
88
+ cfg.Identity = config.Identity{}
89
+
90
+ // setup the node addresses.
91
+ cfg.Addresses = config.Addresses{
92
+ Swarm: "/ip4/0.0.0.0/tcp/4001",
93
+ API: "/ip4/127.0.0.1/tcp/5001",
94
+ }
95
+
96
+ // setup the node mount points.
97
+ cfg.Mounts = config.Mounts{
98
+ IPFS: "/ipfs",
99
+ IPNS: "/ipns",
100
+ }
101
+
102
+ nbits, ok := c.Flag.Lookup("b").Value.Get().(int)
103
+ if !ok {
104
+ return errors.New("failed to get bits flag")
105
+ }
106
+ if nbits < 1024 {
107
+ return errors.New("Bitsize less than 1024 is considered unsafe.")
108
+ }
109
+
110
+ u.POut("generating key pair\n")
111
+ sk, pk, err := ci.GenerateKeyPair(ci.RSA, nbits)
112
+ if err != nil {
113
+ return err
114
+ }
115
+
116
+ // currently storing key unencrypted. in the future we need to encrypt it.
117
+ // TODO(security)
118
+ skbytes, err := sk.Bytes()
119
+ if err != nil {
120
+ return err
121
+ }
122
+ cfg.Identity.PrivKey = base64.StdEncoding.EncodeToString(skbytes)
123
+
124
+ id, err := peer.IDFromPubKey(pk)
125
+ if err != nil {
126
+ return err
127
+ }
128
+ cfg.Identity.PeerID = id.Pretty()
129
+
130
+ // Use these hardcoded bootstrap peers for now.
131
+ cfg.Bootstrap = []*config.BootstrapPeer{
132
+ &config.BootstrapPeer{
133
+ // mars.i.ipfs.io
134
+ PeerID: "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
135
+ Address: "/ip4/104.131.131.82/tcp/4001",
136
+ },
137
+ }
138
+
139
+ // tracking ipfs version used to generate the init folder and adding update checker default setting.
140
+ cfg.Version = config.Version{
141
+ Check: "error",
142
+ Current: updates.Version,
143
+ }
144
+
145
+ err = config.WriteConfigFile(filename, cfg)
146
+ if err != nil {
147
+ return err
148
+ }
149
+ return nil
150
+}
cmd/ipfs/ipfs.go
new
+220
@@ -0,0 +1,220 @@
1
+package main
2
+
3
+import (
4
+ "errors"
5
+ "fmt"
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"
17
+ u "github.com/jbenet/go-ipfs/util"
18
+)
19
+
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
+
81
+// log is the command logger
82
+var log = u.Logger("cmd/ipfs")
83
+
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
+}
97
+
98
+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:])
112
+ if err != nil {
113
+ if len(err.Error()) > 0 {
114
+ fmt.Fprintf(os.Stderr, "ipfs %s: %v\n", os.Args[1], err)
115
+ }
116
+ os.Exit(1)
117
+ }
118
+ return
119
+}
120
+
121
+// localNode constructs a node
122
+func localNode(confdir string, online bool) (*core.IpfsNode, error) {
123
+ filename, err := config.Filename(confdir)
124
+ 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
166
+ }
167
+
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
+}
178
+
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
+ }
184
+
185
+ cc.configDir, err = getConfigDir(rootCmd)
186
+ if err != nil {
187
+ return
188
+ }
189
+
190
+ cc.node, err = localNode(cc.configDir, online)
191
+ if err != nil {
192
+ return
193
+ }
194
+
195
+ cc.daemon, err = setupDaemon(cc.configDir, cc.node)
196
+ if err != nil {
197
+ return
198
+ }
199
+
200
+ return
201
+}
202
+
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
+ }
208
+
209
+ maddr, err := ma.NewMultiaddr(node.Config.Addresses.API)
210
+ if err != nil {
211
+ return nil, err
212
+ }
213
+
214
+ dl, err := daemon.NewDaemonListener(node, maddr, confdir)
215
+ if err != nil {
216
+ return nil, err
217
+ }
218
+ go dl.Listen()
219
+ return dl, nil
220
+}
cmd/ipfs/log.go
new
+29
@@ -0,0 +1,29 @@
1
+package main
2
+
3
+import (
4
+ flag "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5
+ commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
6
+ "github.com/jbenet/go-ipfs/core/commands"
7
+)
8
+
9
+var cmdIpfsLog = &commander.Command{
10
+ UsageLine: "log <name> <level> ",
11
+ Short: "switch logging levels of a running daemon",
12
+ Long: `ipfs log <name> <level> - switch logging levels of a running daemon
13
+
14
+ <name> is a the subsystem logging identifier. Use * for all subsystems.
15
+ <level> is one of: debug, info, notice, warning, error, critical
16
+
17
+ipfs log is a utility command used to change the logging output of a running daemon.
18
+`,
19
+ Run: logCmd,
20
+ Flag: *flag.NewFlagSet("ipfs-log", flag.ExitOnError),
21
+}
22
+
23
+var logCmd = makeCommand(command{
24
+ name: "log",
25
+ args: 2,
26
+ flags: nil,
27
+ online: true,
28
+ cmdFn: commands.Log,
29
+})
cmd/ipfs/ls.go
new
+29
@@ -0,0 +1,29 @@
1
+package main
2
+
3
+import (
4
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
6
+ "github.com/jbenet/go-ipfs/core/commands"
7
+)
8
+
9
+var cmdIpfsLs = &commander.Command{
10
+ UsageLine: "ls",
11
+ Short: "List links from an object.",
12
+ Long: `ipfs ls <ipfs-path> - List links from an object.
13
+
14
+ Retrieves the object named by <ipfs-path> and displays the links
15
+ it contains, with the following format:
16
+
17
+ <link base58 hash> <link size in bytes> <link name>
18
+
19
+`,
20
+ Run: lsCmd,
21
+ Flag: *flag.NewFlagSet("ipfs-ls", flag.ExitOnError),
22
+}
23
+
24
+var lsCmd = makeCommand(command{
25
+ name: "ls",
26
+ args: 1,
27
+ flags: nil,
28
+ cmdFn: commands.Ls,
29
+})
cmd/ipfs/mount_unix.go
new
+94
@@ -0,0 +1,94 @@
1
+// +build linux darwin freebsd
2
+
3
+package main
4
+
5
+import (
6
+ "fmt"
7
+
8
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
9
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
10
+
11
+ core "github.com/jbenet/go-ipfs/core"
12
+ ipns "github.com/jbenet/go-ipfs/fuse/ipns"
13
+ rofs "github.com/jbenet/go-ipfs/fuse/readonly"
14
+)
15
+
16
+var cmdIpfsMount = &commander.Command{
17
+ UsageLine: "mount",
18
+ Short: "Mount an ipfs read-only mountpoint.",
19
+ Long: `ipfs mount <os-path> - Mount an ipfs read-only mountpoint.
20
+
21
+ Mount ipfs at a read-only mountpoint on the OS. All ipfs objects
22
+ will be accessible under that directory. Note that the root will
23
+ not be listable, as it is virtual. Accessing known paths directly.
24
+
25
+`,
26
+ Run: mountCmd,
27
+ Flag: *flag.NewFlagSet("ipfs-mount", flag.ExitOnError),
28
+}
29
+
30
+func init() {
31
+ cmdIpfsMount.Flag.String("f", "", "specify a mountpoint for ipfs")
32
+ cmdIpfsMount.Flag.String("n", "", "specify a mountpoint for ipns")
33
+}
34
+
35
+func mountCmd(c *commander.Command, inp []string) error {
36
+
37
+ cc, err := setupCmdContext(c, true)
38
+ if err != nil {
39
+ return err
40
+ }
41
+ defer cc.daemon.Close()
42
+
43
+ // update fsdir with flag.
44
+ fsdir := cc.node.Config.Mounts.IPFS
45
+ if val, ok := c.Flag.Lookup("f").Value.Get().(string); ok && val != "" {
46
+ fsdir = val
47
+ }
48
+ fsdone := mountIpfs(cc.node, fsdir)
49
+
50
+ // get default mount points
51
+ nsdir := cc.node.Config.Mounts.IPNS
52
+ if val, ok := c.Flag.Lookup("n").Value.Get().(string); ok && val != "" {
53
+ nsdir = val
54
+ }
55
+ nsdone := mountIpns(cc.node, nsdir, fsdir)
56
+
57
+ // wait till mounts are done.
58
+ err1 := <-fsdone
59
+ err2 := <-nsdone
60
+
61
+ if err1 != nil {
62
+ return err1
63
+ }
64
+ return err2
65
+}
66
+
67
+func mountIpfs(node *core.IpfsNode, fsdir string) <-chan error {
68
+ done := make(chan error)
69
+ fmt.Printf("mounting ipfs at %s\n", fsdir)
70
+
71
+ go func() {
72
+ err := rofs.Mount(node, fsdir)
73
+ done <- err
74
+ close(done)
75
+ }()
76
+
77
+ return done
78
+}
79
+
80
+func mountIpns(node *core.IpfsNode, nsdir, fsdir string) <-chan error {
81
+ if nsdir == "" {
82
+ return nil
83
+ }
84
+ done := make(chan error)
85
+ fmt.Printf("mounting ipns at %s\n", nsdir)
86
+
87
+ go func() {
88
+ err := ipns.Mount(node, nsdir, fsdir)
89
+ done <- err
90
+ close(done)
91
+ }()
92
+
93
+ return done
94
+}
cmd/ipfs/mount_windows.go
new
+19
@@ -0,0 +1,19 @@
1
+package main
2
+
3
+import (
4
+ "errors"
5
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
6
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
7
+)
8
+
9
+var cmdIpfsMount = &commander.Command{
10
+ UsageLine: "mount",
11
+ Short: "Mount an ipfs read-only mountpoint.",
12
+ Long: `Not yet implemented on windows.`,
13
+ Run: mountCmd,
14
+ Flag: *flag.NewFlagSet("ipfs-mount", flag.ExitOnError),
15
+}
16
+
17
+func mountCmd(c *commander.Command, inp []string) error {
18
+ return errors.New("mount not yet implemented on windows")
19
+}
cmd/ipfs/name.go
new
+57
@@ -0,0 +1,57 @@
1
+package main
2
+
3
+import (
4
+ "fmt"
5
+
6
+ flag "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
7
+ commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
8
+)
9
+
10
+var cmdIpfsName = &commander.Command{
11
+ UsageLine: "name [publish | resolve]",
12
+ Short: "ipfs namespace (ipns) tool",
13
+ Long: `ipfs name - Get/Set ipfs config values.
14
+
15
+ ipfs name publish [<name>] <ref> - Assign the <ref> to <name>
16
+ ipfs name resolve [<name>] - Resolve the <ref> value of <name>
17
+
18
+IPNS is a PKI namespace, where names are the hashes of public keys, and
19
+the private key enables publishing new (signed) values. In both publish
20
+and resolve, the default value of <name> is your own identity public key.
21
+
22
+
23
+Examples:
24
+
25
+Publish a <ref> to your identity name:
26
+
27
+ > ipfs name publish QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
28
+ published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
29
+
30
+Publish a <ref> to another public key:
31
+
32
+ > ipfs name publish QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
33
+ published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
34
+
35
+Resolve the value of your identity:
36
+
37
+ > ipfs name resolve
38
+ QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
39
+
40
+Resolve te value of another name:
41
+
42
+ > ipfs name resolve QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
43
+ QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
44
+
45
+`,
46
+ Run: nameCmd,
47
+ Flag: *flag.NewFlagSet("ipfs-name", flag.ExitOnError),
48
+ Subcommands: []*commander.Command{
49
+ cmdIpfsPub,
50
+ cmdIpfsResolve,
51
+ },
52
+}
53
+
54
+func nameCmd(c *commander.Command, args []string) error {
55
+ fmt.Println(c.Long)
56
+ return nil
57
+}
cmd/ipfs/objects.go
new
+112
@@ -0,0 +1,112 @@
1
+package main
2
+
3
+import (
4
+ flag "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5
+ commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
6
+ "github.com/jbenet/go-ipfs/core/commands"
7
+)
8
+
9
+var cmdIpfsObject = &commander.Command{
10
+ UsageLine: "object",
11
+ Short: "interact with ipfs objects",
12
+ Long: `ipfs object - interact with ipfs objects
13
+
14
+ ipfs object data <key> - return the data for this key as raw bytes
15
+ ipfs object links <key> - lists (the keys of ?) the links this key points to
16
+ ipfs object get <key> - output dag object to stdout
17
+ ipfs object put - add dag object from stdin
18
+
19
+ipfs object is a plumbing command used to manipulate dag objects directly.
20
+- <key> is a base58 encoded multihash.
21
+- It reads from stdin or writes to stdout.
22
+- It accepts multiple encodings: --encoding=[ protobuf, json, ... ]`,
23
+ Subcommands: []*commander.Command{
24
+ cmdIpfsObjectData,
25
+ cmdIpfsObjectLinks,
26
+ cmdIpfsObjectGet,
27
+ cmdIpfsObjectPut,
28
+ },
29
+ Flag: *flag.NewFlagSet("ipfs-object", flag.ExitOnError),
30
+}
31
+
32
+var cmdIpfsObjectData = &commander.Command{
33
+ UsageLine: "data <key>",
34
+ Short: "data outputs the raw bytes named by <key>",
35
+ Long: `ipfs data <key> - data outputs the raw bytes named by <key>
36
+
37
+ipfs data is a plumbing command for retreiving the raw bytes stored in a dag node.
38
+It outputs to stdout, and <key> is a base58 encoded multihash.`,
39
+ Run: makeCommand(command{
40
+ name: "objectData",
41
+ args: 1,
42
+ flags: nil,
43
+ online: true,
44
+ cmdFn: commands.ObjectData,
45
+ }),
46
+}
47
+
48
+var cmdIpfsObjectLinks = &commander.Command{
49
+ UsageLine: "links <key>",
50
+ Short: "outputs the links pointed to by <key>",
51
+ Long: `ipfs links <key> - outputs the links pointed to by <key>
52
+
53
+ipfs block get is a plumbing command for retreiving raw ipfs blocks.
54
+It outputs to stdout, and <key> is a base58 encoded multihash.`,
55
+ Run: makeCommand(command{
56
+ name: "objectLinks",
57
+ args: 1,
58
+ flags: nil,
59
+ online: true,
60
+ cmdFn: commands.ObjectLinks,
61
+ }),
62
+}
63
+
64
+func init() {
65
+ cmdIpfsObjectGet.Flag.String("encoding", "json", "the encoding to use..")
66
+ cmdIpfsObjectPut.Flag.String("encoding", "json", "the encoding to use..")
67
+}
68
+
69
+var cmdIpfsObjectGet = &commander.Command{
70
+ UsageLine: "get <key>",
71
+ Short: "get and serialize the dag node named by <key>",
72
+ Long: `ipfs get <key> - get and output the dag node named by <key>
73
+
74
+ipfs object get is a plumbing command for retreiving dag nodes.
75
+It serialize the dag node to the format specified by the format flag.
76
+It outputs to stdout, and <key> is a base58 encoded multihash.
77
+
78
+Formats:
79
+
80
+This command outputs and accepts data in a variety of encodings: protobuf, json, etc.
81
+Use the --encoding flag
82
+`,
83
+ Run: makeCommand(command{
84
+ name: "blockGet",
85
+ args: 1,
86
+ flags: []string{"encoding"},
87
+ online: true,
88
+ cmdFn: commands.ObjectGet,
89
+ }),
90
+}
91
+
92
+var cmdIpfsObjectPut = &commander.Command{
93
+ UsageLine: "put",
94
+ Short: "store stdin as a dag object, outputs <key>",
95
+ Long: `ipfs put - store stdin as a dag object, outputs <key>
96
+
97
+ipfs object put is a plumbing command for storing dag nodes.
98
+It serialize the dag node to the format specified by the format flag.
99
+It reads from stding, and <key> is a base58 encoded multihash.
100
+
101
+Formats:
102
+
103
+This command outputs and accepts data in a variety of encodings: protobuf, json, etc.
104
+Use the --encoding flag`,
105
+ Run: makeCommand(command{
106
+ name: "blockPut",
107
+ args: 0,
108
+ flags: []string{"encoding"},
109
+ online: true,
110
+ cmdFn: commands.ObjectPut,
111
+ }),
112
+}
cmd/ipfs/pin.go
new
+62
@@ -0,0 +1,62 @@
1
+package main
2
+
3
+import (
4
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
6
+ "github.com/jbenet/go-ipfs/core/commands"
7
+)
8
+
9
+var cmdIpfsPin = &commander.Command{
10
+ UsageLine: "pin",
11
+ Short: "",
12
+ Long: `ipfs pin [add|rm] - object pinning commands
13
+`,
14
+ Subcommands: []*commander.Command{
15
+ cmdIpfsSubPin,
16
+ cmdIpfsSubUnpin,
17
+ },
18
+}
19
+
20
+var cmdIpfsSubPin = &commander.Command{
21
+ UsageLine: "add",
22
+ Short: "pin an ipfs object to local storage.",
23
+ Long: `ipfs pin add <ipfs-path> - pin ipfs object to local storage.
24
+
25
+ Retrieves the object named by <ipfs-path> and stores it locally
26
+ on disk.
27
+`,
28
+ Run: pinSubCmd,
29
+ Flag: *flag.NewFlagSet("ipfs-pin", flag.ExitOnError),
30
+}
31
+
32
+var pinSubCmd = makeCommand(command{
33
+ name: "pin",
34
+ args: 1,
35
+ flags: []string{"r", "d"},
36
+ cmdFn: commands.Pin,
37
+})
38
+
39
+var cmdIpfsSubUnpin = &commander.Command{
40
+ UsageLine: "rm",
41
+ Short: "unpin an ipfs object from local storage.",
42
+ Long: `ipfs pin rm <ipfs-path> - unpin ipfs object from local storage.
43
+
44
+ Removes the pin from the given object allowing it to be garbage
45
+ collected if needed.
46
+`,
47
+ Run: unpinSubCmd,
48
+ Flag: *flag.NewFlagSet("ipfs-unpin", flag.ExitOnError),
49
+}
50
+
51
+var unpinSubCmd = makeCommand(command{
52
+ name: "unpin",
53
+ args: 1,
54
+ flags: []string{"r"},
55
+ cmdFn: commands.Unpin,
56
+})
57
+
58
+func init() {
59
+ cmdIpfsSubPin.Flag.Bool("r", false, "pin objects recursively")
60
+ cmdIpfsSubPin.Flag.Int("d", 1, "recursive depth")
61
+ cmdIpfsSubUnpin.Flag.Bool("r", false, "unpin objects recursively")
62
+}
cmd/ipfs/publish.go
new
+41
@@ -0,0 +1,41 @@
1
+package main
2
+
3
+import (
4
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
6
+ "github.com/jbenet/go-ipfs/core/commands"
7
+)
8
+
9
+var cmdIpfsPub = &commander.Command{
10
+ UsageLine: "publish",
11
+ Short: "publish a <ref> to ipns.",
12
+ Long: `ipfs publish [<name>] <ref> - publish a <ref> to ipns.
13
+
14
+IPNS is a PKI namespace, where names are the hashes of public keys, and
15
+the private key enables publishing new (signed) values. In publish, the
16
+default value of <name> is your own identity public key.
17
+
18
+Examples:
19
+
20
+Publish a <ref> to your identity name:
21
+
22
+ > ipfs name publish QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
23
+ published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
24
+
25
+Publish a <ref> to another public key:
26
+
27
+ > ipfs name publish QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
28
+ published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
29
+
30
+`,
31
+ Run: pubCmd,
32
+ Flag: *flag.NewFlagSet("ipfs-publish", flag.ExitOnError),
33
+}
34
+
35
+var pubCmd = makeCommand(command{
36
+ name: "publish",
37
+ args: 1,
38
+ flags: nil,
39
+ online: true,
40
+ cmdFn: commands.Publish,
41
+})
cmd/ipfs/refs.go
new
+36
@@ -0,0 +1,36 @@
1
+package main
2
+
3
+import (
4
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
6
+ commands "github.com/jbenet/go-ipfs/core/commands"
7
+)
8
+
9
+var cmdIpfsRefs = &commander.Command{
10
+ UsageLine: "refs",
11
+ Short: "List link hashes from an object.",
12
+ Long: `ipfs refs <ipfs-path> - List link hashes from an object..
13
+
14
+ Retrieves the object named by <ipfs-path> and displays the link
15
+ hashes it contains, with the following format:
16
+
17
+ <link base58 hash>
18
+
19
+ Note: list all refs recursively with -r.
20
+
21
+`,
22
+ Run: refCmd,
23
+ Flag: *flag.NewFlagSet("ipfs-refs", flag.ExitOnError),
24
+}
25
+
26
+func init() {
27
+ cmdIpfsRefs.Flag.Bool("r", false, "recursive: list refs recursively")
28
+ cmdIpfsRefs.Flag.Bool("u", false, "unique: list each ref only once")
29
+}
30
+
31
+var refCmd = makeCommand(command{
32
+ name: "refs",
33
+ args: 1,
34
+ flags: []string{"r", "u"},
35
+ cmdFn: commands.Refs,
36
+})
cmd/ipfs/resolve.go
new
+42
@@ -0,0 +1,42 @@
1
+package main
2
+
3
+import (
4
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
6
+ "github.com/jbenet/go-ipfs/core/commands"
7
+)
8
+
9
+var cmdIpfsResolve = &commander.Command{
10
+ UsageLine: "resolve",
11
+ Short: "resolve an ipns name to a <ref>",
12
+ Long: `ipfs resolve [<name>] - Resolve an ipns name to a <ref>.
13
+
14
+IPNS is a PKI namespace, where names are the hashes of public keys, and
15
+the private key enables publishing new (signed) values. In resolve, the
16
+default value of <name> is your own identity public key.
17
+
18
+
19
+Examples:
20
+
21
+Resolve the value of your identity:
22
+
23
+ > ipfs name resolve
24
+ QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
25
+
26
+Resolve te value of another name:
27
+
28
+ > ipfs name resolve QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
29
+ QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
30
+
31
+`,
32
+ Run: resolveCmd,
33
+ Flag: *flag.NewFlagSet("ipfs-resolve", flag.ExitOnError),
34
+}
35
+
36
+var resolveCmd = makeCommand(command{
37
+ name: "resolve",
38
+ args: 0,
39
+ flags: nil,
40
+ online: true,
41
+ cmdFn: commands.Resolve,
42
+})
cmd/ipfs/run.go
new
+36
@@ -0,0 +1,36 @@
1
+package main
2
+
3
+import (
4
+ "os"
5
+ "os/signal"
6
+ "syscall"
7
+
8
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
9
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
10
+)
11
+
12
+var cmdIpfsRun = &commander.Command{
13
+ UsageLine: "run",
14
+ Short: "run local ifps node.",
15
+ Long: `run a local ipfs node with no other interface.
16
+`,
17
+ Run: runCmd,
18
+ Flag: *flag.NewFlagSet("ipfs-run", flag.ExitOnError),
19
+}
20
+
21
+func runCmd(c *commander.Command, inp []string) error {
22
+ cc, err := setupCmdContext(c, true)
23
+ if err != nil {
24
+ return err
25
+ }
26
+
27
+ sigc := make(chan os.Signal, 1)
28
+ signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT,
29
+ syscall.SIGTERM, syscall.SIGQUIT)
30
+
31
+ // wait until we get a signal to exit.
32
+ <-sigc
33
+
34
+ cc.daemon.Close()
35
+ return nil
36
+}
cmd/ipfs/serve.go
new
+49
@@ -0,0 +1,49 @@
1
+package main
2
+
3
+import (
4
+ "fmt"
5
+
6
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
7
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
8
+ ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
9
+
10
+ h "github.com/jbenet/go-ipfs/server/http"
11
+)
12
+
13
+var cmdIpfsServe = &commander.Command{
14
+ UsageLine: "serve",
15
+ Short: "Serve an interface to ipfs",
16
+ Subcommands: []*commander.Command{
17
+ cmdIpfsServeHTTP,
18
+ },
19
+ Flag: *flag.NewFlagSet("ipfs-serve", flag.ExitOnError),
20
+}
21
+
22
+var cmdIpfsServeHTTP = &commander.Command{
23
+ UsageLine: "http",
24
+ Short: "Serve an HTTP API",
25
+ Long: `ipfs serve http - Serve an http gateway into ipfs.`,
26
+ Run: serveHTTPCmd,
27
+ Flag: *flag.NewFlagSet("ipfs-serve-http", flag.ExitOnError),
28
+}
29
+
30
+func init() {
31
+ cmdIpfsServeHTTP.Flag.String("address", "/ip4/127.0.0.1/tcp/8080", "Listen Address")
32
+}
33
+
34
+func serveHTTPCmd(c *commander.Command, _ []string) error {
35
+ cc, err := setupCmdContext(c, true)
36
+ if err != nil {
37
+ return err
38
+ }
39
+ defer cc.daemon.Close()
40
+
41
+ address := c.Flag.Lookup("address").Value.Get().(string)
42
+ maddr, err := ma.NewMultiaddr(address)
43
+ if err != nil {
44
+ return err
45
+ }
46
+
47
+ fmt.Printf("Serving on %s\n", address)
48
+ return h.Serve(maddr, cc.node)
49
+}
cmd/ipfs/tour.go
new
+134
@@ -0,0 +1,134 @@
1
+// +build linux darwin freebsd
2
+
3
+package main
4
+
5
+import (
6
+ "fmt"
7
+
8
+ config "github.com/jbenet/go-ipfs/config"
9
+ tour "github.com/jbenet/go-ipfs/tour"
10
+
11
+ commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
12
+)
13
+
14
+var cmdIpfsTour = &commander.Command{
15
+ UsageLine: "tour [<number>]",
16
+ Short: "Take the IPFS Tour.",
17
+ Long: `ipfs tour - Take the IPFS Tour.
18
+
19
+ ipfs tour [<number>] - Show tour topic. Default to current.
20
+ ipfs tour next - Show the next tour topic.
21
+ ipfs tour list - Show a list of topics.
22
+ ipfs tour restart - Restart the tour.
23
+
24
+This is a tour that takes you through various IPFS concepts,
25
+features, and tools to make sure you get up to speed with
26
+IPFS very quickly. To start, run:
27
+
28
+ ipfs tour
29
+`,
30
+ Run: tourCmd,
31
+ Subcommands: []*commander.Command{
32
+ cmdIpfsTourNext,
33
+ cmdIpfsTourList,
34
+ cmdIpfsTourRestart,
35
+ },
36
+}
37
+
38
+var cmdIpfsTourNext = &commander.Command{
39
+ UsageLine: "next",
40
+ Short: "Show the next IPFS Tour topic.",
41
+ Run: tourNextCmd,
42
+}
43
+
44
+var cmdIpfsTourList = &commander.Command{
45
+ UsageLine: "list",
46
+ Short: "Show a list of IPFS Tour topics.",
47
+ Run: tourListCmd,
48
+}
49
+
50
+var cmdIpfsTourRestart = &commander.Command{
51
+ UsageLine: "restart",
52
+ Short: "Restart the IPFS Tour.",
53
+ Run: tourRestartCmd,
54
+}
55
+
56
+func tourCmd(c *commander.Command, inp []string) error {
57
+ cfg, err := getConfig(c)
58
+ if err != nil {
59
+ return err
60
+ }
61
+
62
+ topic := tour.TopicID(cfg.Tour.Last)
63
+ if len(inp) > 0 {
64
+ topic = tour.TopicID(inp[0])
65
+ }
66
+ return tourShow(topic)
67
+}
68
+
69
+func tourNextCmd(c *commander.Command, _ []string) error {
70
+ cfg, err := getConfig(c)
71
+ if err != nil {
72
+ return err
73
+ }
74
+
75
+ topic := tour.NextTopic(tour.TopicID(cfg.Tour.Last))
76
+ if err := tourShow(topic); err != nil {
77
+ return err
78
+ }
79
+
80
+ // if topic didn't change (last) done
81
+ if string(topic) == cfg.Tour.Last {
82
+ return nil
83
+ }
84
+
85
+ // topic changed, not last. write it out.
86
+ cfg.Tour.Last = string(topic)
87
+ return writeConfig(c, cfg)
88
+}
89
+
90
+func tourListCmd(c *commander.Command, _ []string) error {
91
+ cfg, err := getConfig(c)
92
+ if err != nil {
93
+ return err
94
+ }
95
+ lastid := tour.TopicID(cfg.Tour.Last)
96
+
97
+ for _, id := range tour.IDs {
98
+ c := ' '
99
+ switch {
100
+ case id == lastid:
101
+ c = '*'
102
+ case id.LessThan(lastid):
103
+ c = '✓'
104
+ }
105
+
106
+ t := tour.Topics[id]
107
+ fmt.Printf("- %c %-5.5s %s\n", c, id, t.Title)
108
+ }
109
+ return nil
110
+}
111
+
112
+func tourRestartCmd(c *commander.Command, _ []string) error {
113
+ cfg, err := getConfig(c)
114
+ if err != nil {
115
+ return err
116
+ }
117
+
118
+ cfg.Tour.Last = ""
119
+ return writeConfig(c, cfg)
120
+}
121
+
122
+func tourShow(id tour.ID) error {
123
+ t, found := tour.Topics[id]
124
+ if !found {
125
+ return fmt.Errorf("no topic with id: %s", id)
126
+ }
127
+
128
+ fmt.Printf("Tour %s - %s\n\n%s\n", t.ID, t.Title, t.Text)
129
+ return nil
130
+}
131
+
132
+func lastTour(cfg *config.Config) string {
133
+ return ""
134
+}
cmd/ipfs/update.go
new
+62
@@ -0,0 +1,62 @@
1
+package main
2
+
3
+import (
4
+ flag "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
5
+ commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
6
+ "github.com/jbenet/go-ipfs/core/commands"
7
+)
8
+
9
+func init() {
10
+ cmdIpfsUpdate.Flag.Bool("force", false, "force shutdown of daemon when updating")
11
+}
12
+
13
+var cmdIpfsUpdate = &commander.Command{
14
+ UsageLine: "update",
15
+ Short: "check for updates and apply them",
16
+ Long: `ipfs update - check for updates and apply them
17
+
18
+ ipfs update <version> - apply
19
+ ipfs update check - just check
20
+ ipfs update log - list the changelogs
21
+
22
+ipfs update is a utility command used to check for updates and apply them.
23
+I wont even try, @jbenet. You do this much better :)`,
24
+ Run: makeCommand(command{
25
+ name: "updateApply",
26
+ args: 0,
27
+ flags: []string{"force"},
28
+ online: true,
29
+ cmdFn: commands.UpdateApply,
30
+ }),
31
+ Subcommands: []*commander.Command{
32
+ cmdIpfsUpdateCheck,
33
+ cmdIpfsUpdateLog,
34
+ },
35
+ Flag: *flag.NewFlagSet("ipfs-update", flag.ExitOnError),
36
+}
37
+
38
+var cmdIpfsUpdateCheck = &commander.Command{
39
+ UsageLine: "check",
40
+ Short: "",
41
+ Long: `ipfs update check <key>`,
42
+ Run: makeCommand(command{
43
+ name: "updateCheck",
44
+ args: 0,
45
+ flags: nil,
46
+ online: false,
47
+ cmdFn: commands.UpdateCheck,
48
+ }),
49
+}
50
+
51
+var cmdIpfsUpdateLog = &commander.Command{
52
+ UsageLine: "log",
53
+ Short: "list the last versions and their changelog",
54
+ Long: `ipfs updage log - list the last versions and their changelog`,
55
+ Run: makeCommand(command{
56
+ name: "updateLog",
57
+ args: 0,
58
+ flags: nil,
59
+ online: false,
60
+ cmdFn: commands.UpdateCheck,
61
+ }),
62
+}
cmd/ipfs/version.go
new
+30
@@ -0,0 +1,30 @@
1
+package main
2
+
3
+import (
4
+ "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
5
+ updates "github.com/jbenet/go-ipfs/updates"
6
+ u "github.com/jbenet/go-ipfs/util"
7
+)
8
+
9
+var cmdIpfsVersion = &commander.Command{
10
+ UsageLine: "version",
11
+ Short: "Show ipfs version information.",
12
+ Long: `ipfs version - Show ipfs version information.
13
+
14
+ Returns the current version of ipfs and exits.
15
+ `,
16
+ Run: versionCmd,
17
+}
18
+
19
+func init() {
20
+ cmdIpfsVersion.Flag.Bool("number", false, "show only the number")
21
+}
22
+
23
+func versionCmd(c *commander.Command, _ []string) error {
24
+ number := c.Flag.Lookup("number").Value.Get().(bool)
25
+ if !number {
26
+ u.POut("ipfs version ")
27
+ }
28
+ u.POut("%s\n", updates.Version)
29
+ return nil
30
+}