1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-07-01 02:30:39 +08:00

copy to old location

This commit is contained in:
Brian Tiger Chow
2014-10-28 23:48:11 -07:00
committed by Juan Batiz-Benet
parent bc6800035b
commit d1fa4bd9b5
29 changed files with 1925 additions and 0 deletions

1
cmd/ipfs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
./ipfs

7
cmd/ipfs/Makefile Normal file
View File

@ -0,0 +1,7 @@
all: install
build:
go build
install: build
go install

29
cmd/ipfs/README.md Normal file
View File

@ -0,0 +1,29 @@
# go-ipfs/cmd/ipfs
This is the ipfs commandline tool. For now, it's the main entry point to using IPFS. Use it.
```
> go build
> go install
> ipfs
ipfs - global versioned p2p merkledag file system
Basic commands:
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.
version Show ipfs version information.
commands List all available commands.
Advanced Commands:
mount Mount an ipfs read-only mountpoint.
Use "ipfs help <command>" for more information about a command.
```

39
cmd/ipfs/add.go Normal file
View File

@ -0,0 +1,39 @@
package main
import (
"fmt"
"path/filepath"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
"github.com/jbenet/go-ipfs/core/commands"
)
// Error indicating the max depth has been exceded.
var ErrDepthLimitExceeded = fmt.Errorf("depth limit exceeded")
var cmdIpfsAdd = &commander.Command{
UsageLine: "add",
Short: "Add an object to ipfs.",
Long: `ipfs add <path>... - Add objects to ipfs.
Adds contents of <path> to ipfs. Use -r to add directories.
Note that directories are added recursively, to form the ipfs
MerkleDAG. A smarter partial add with a staging area (like git)
remains to be implemented.
`,
Run: addCmd,
Flag: *flag.NewFlagSet("ipfs-add", flag.ExitOnError),
}
func init() {
cmdIpfsAdd.Flag.Bool("r", false, "add objects recursively")
}
var addCmd = makeCommand(command{
name: "add",
args: 1,
flags: []string{"r"},
cmdFn: commands.Add,
argFilter: filepath.Abs,
})

58
cmd/ipfs/block.go Normal file
View File

@ -0,0 +1,58 @@
package main
import (
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"
"github.com/jbenet/go-ipfs/core/commands"
)
var cmdIpfsBlock = &commander.Command{
UsageLine: "block",
Short: "manipulate raw ipfs blocks",
Long: `ipfs block - manipulate raw ipfs blocks
ipfs block get <key> - get and output block named by <key>
ipfs block put - store stdin as a block, outputs <key>
ipfs block is a plumbing command used to manipulate raw ipfs blocks.
Reads from stdin or writes to stdout, and <key> is a base58 encoded
multihash.`,
// Run: blockGetCmd,
Subcommands: []*commander.Command{
cmdIpfsBlockGet,
cmdIpfsBlockPut,
},
Flag: *flag.NewFlagSet("ipfs-block", flag.ExitOnError),
}
var cmdIpfsBlockGet = &commander.Command{
UsageLine: "get <key>",
Short: "get and output block named by <key>",
Long: `ipfs get <key> - get and output block named by <key>
ipfs block get is a plumbing command for retreiving raw ipfs blocks.
It outputs to stdout, and <key> is a base58 encoded multihash.`,
Run: makeCommand(command{
name: "blockGet",
args: 1,
flags: nil,
online: true,
cmdFn: commands.BlockGet,
}),
}
var cmdIpfsBlockPut = &commander.Command{
UsageLine: "put",
Short: "store stdin as a block, outputs <key>",
Long: `ipfs put - store stdin as a block, outputs <key>
ipfs block put is a plumbing command for storing raw ipfs blocks.
It reads from stding, and <key> is a base58 encoded multihash.`,
Run: makeCommand(command{
name: "blockPut",
args: 0,
flags: nil,
online: true,
cmdFn: commands.BlockPut,
}),
}

236
cmd/ipfs/bootstrap.go Normal file
View File

@ -0,0 +1,236 @@
package main
import (
"errors"
"strings"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"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"
mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
config "github.com/jbenet/go-ipfs/config"
peer "github.com/jbenet/go-ipfs/peer"
u "github.com/jbenet/go-ipfs/util"
)
var cmdIpfsBootstrap = &commander.Command{
UsageLine: "bootstrap",
Short: "Show a list of bootstrapped addresses.",
Long: `ipfs bootstrap - show, or manipulate bootstrap node addresses
Running 'ipfs bootstrap' with no arguments will run 'ipfs bootstrap list'.
Commands:
list Show the boostrap list.
add <address> Add a node's address to the bootstrap list.
remove <address> Remove an address from the bootstrap list.
` + bootstrapSecurityWarning,
Run: bootstrapListCmd,
Subcommands: []*commander.Command{
cmdIpfsBootstrapRemove,
cmdIpfsBootstrapAdd,
cmdIpfsBootstrapList,
},
Flag: *flag.NewFlagSet("ipfs-bootstrap", flag.ExitOnError),
}
var cmdIpfsBootstrapRemove = &commander.Command{
UsageLine: "remove <address | peerid>",
Short: "Remove addresses from the bootstrap list.",
Long: `ipfs bootstrap remove - remove addresses from the bootstrap list
` + bootstrapSecurityWarning,
Run: bootstrapRemoveCmd,
Flag: *flag.NewFlagSet("ipfs-bootstrap-remove", flag.ExitOnError),
}
var cmdIpfsBootstrapAdd = &commander.Command{
UsageLine: "add <address | peerid>",
Short: "Add addresses to the bootstrap list.",
Long: `ipfs bootstrap add - add addresses to the bootstrap list
` + bootstrapSecurityWarning,
Run: bootstrapAddCmd,
Flag: *flag.NewFlagSet("ipfs-bootstrap-add", flag.ExitOnError),
}
var cmdIpfsBootstrapList = &commander.Command{
UsageLine: "list",
Short: "Show addresses in the bootstrap list.",
Run: bootstrapListCmd,
Flag: *flag.NewFlagSet("ipfs-bootstrap-list", flag.ExitOnError),
}
func bootstrapRemoveCmd(c *commander.Command, inp []string) error {
if len(inp) == 0 {
return errors.New("remove: no address or peerid specified")
}
toRemove, err := bootstrapInputToPeers(inp)
if err != nil {
return err
}
cfg, err := getConfig(c)
if err != nil {
return err
}
keep := []*config.BootstrapPeer{}
remove := []*config.BootstrapPeer{}
// function to filer what to keep
shouldKeep := func(bp *config.BootstrapPeer) bool {
for _, skipBP := range toRemove {
// IDs must match to skip.
if bp.PeerID != skipBP.PeerID {
continue
}
// if Addresses match, or skipBP has no addr (wildcard)
if skipBP.Address == bp.Address || skipBP.Address == "" {
return false
}
}
return true
}
// filter all the existing peers
for _, currBP := range cfg.Bootstrap {
if shouldKeep(currBP) {
keep = append(keep, currBP)
} else {
remove = append(remove, currBP)
}
}
// if didn't remove anyone, bail.
if len(keep) == len(cfg.Bootstrap) {
return errors.New("remove: peer given did not match any in list")
}
// write new config
cfg.Bootstrap = keep
if err := writeConfig(c, cfg); err != nil {
return err
}
for _, bp := range remove {
u.POut("removed %s\n", bp)
}
return nil
}
func bootstrapAddCmd(c *commander.Command, inp []string) error {
if len(inp) == 0 {
return errors.New("add: no address specified")
}
toAdd, err := bootstrapInputToPeers(inp)
if err != nil {
return err
}
cfg, err := getConfig(c)
if err != nil {
return err
}
// function to check whether a peer is already in the list.
combine := func(lists ...[]*config.BootstrapPeer) []*config.BootstrapPeer {
set := map[string]struct{}{}
final := []*config.BootstrapPeer{}
for _, list := range lists {
for _, peer := range list {
// if already in the set, continue
_, found := set[peer.String()]
if found {
continue
}
set[peer.String()] = struct{}{}
final = append(final, peer)
}
}
return final
}
// combine both lists, removing dups.
cfg.Bootstrap = combine(cfg.Bootstrap, toAdd)
if err := writeConfig(c, cfg); err != nil {
return err
}
for _, bp := range toAdd {
u.POut("added %s\n", bp)
}
return nil
}
func bootstrapListCmd(c *commander.Command, inp []string) error {
cfg, err := getConfig(c)
if err != nil {
return err
}
for _, bp := range cfg.Bootstrap {
u.POut("%s\n", bp)
}
return nil
}
func bootstrapInputToPeers(input []string) ([]*config.BootstrapPeer, error) {
split := func(addr string) (string, string) {
idx := strings.LastIndex(addr, "/")
if idx == -1 {
return "", addr
}
return addr[:idx], addr[idx+1:]
}
peers := []*config.BootstrapPeer{}
for _, addr := range input {
addrS, peeridS := split(addr)
// make sure addrS parses as a multiaddr.
if len(addrS) > 0 {
maddr, err := ma.NewMultiaddr(addrS)
if err != nil {
return nil, err
}
addrS = maddr.String()
}
// make sure idS parses as a peer.ID
peerid, err := mh.FromB58String(peeridS)
if err != nil {
return nil, err
}
// construct config entry
peers = append(peers, &config.BootstrapPeer{
Address: addrS,
PeerID: peer.ID(peerid).Pretty(),
})
}
return peers, nil
}
const bootstrapSecurityWarning = `
SECURITY WARNING:
The bootstrap command manipulates the "bootstrap list", which contains
the addresses of bootstrap nodes. These are the *trusted peers* from
which to learn about other peers in the network. Only edit this list
if you understand the risks of adding or removing nodes from this list.
`

26
cmd/ipfs/cat.go Normal file
View File

@ -0,0 +1,26 @@
package main
import (
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
"github.com/jbenet/go-ipfs/core/commands"
)
var cmdIpfsCat = &commander.Command{
UsageLine: "cat",
Short: "Show ipfs object data.",
Long: `ipfs cat <ipfs-path> - Show ipfs object data.
Retrieves the object named by <ipfs-path> and displays the Data
it contains.
`,
Run: catCmd,
Flag: *flag.NewFlagSet("ipfs-cat", flag.ExitOnError),
}
var catCmd = makeCommand(command{
name: "cat",
args: 1,
flags: nil,
cmdFn: commands.Cat,
})

74
cmd/ipfs/commands.go Normal file
View File

@ -0,0 +1,74 @@
package main
import (
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
u "github.com/jbenet/go-ipfs/util"
"strings"
"time"
)
var cmdIpfsCommands = &commander.Command{
UsageLine: "commands",
Short: "List all available commands.",
Long: `ipfs commands - List all available commands.
Lists all available commands (and sub-commands) and exits.
`,
Run: commandsCmd,
Subcommands: []*commander.Command{
cmdIpfsCommandsHelp,
},
}
func commandsCmd(c *commander.Command, args []string) error {
var listCmds func(c *commander.Command)
listCmds = func(c *commander.Command) {
u.POut("%s\n", c.FullSpacedName())
for _, sc := range c.Subcommands {
listCmds(sc)
}
}
listCmds(c.Parent)
return nil
}
var cmdIpfsCommandsHelp = &commander.Command{
UsageLine: "help",
Short: "List all available commands' help pages.",
Long: `ipfs commands help - List all available commands's help pages.
Shows the pages of all available commands (and sub-commands) and exits.
Outputs a markdown document.
`,
Run: commandsHelpCmd,
}
func commandsHelpCmd(c *commander.Command, args []string) error {
u.POut(referenceHeaderMsg)
u.POut("Generated on %s.\n\n", time.Now().UTC().Format("2006-01-02"))
var printCmds func(*commander.Command, int)
printCmds = func(c *commander.Command, level int) {
u.POut("%s ", strings.Repeat("#", level))
u.POut("%s\n\n", c.FullSpacedName())
u.POut("```\n")
u.POut("%s\n", c.Long)
u.POut("```\n\n")
for _, sc := range c.Subcommands {
printCmds(sc, level+1)
}
}
printCmds(c.Parent.Parent, 1)
return nil
}
const referenceHeaderMsg = `
# ipfs command reference
This document lists every ipfs command (including subcommands), along with
its help page. It can be viewed by running 'ipfs commands help'.
`

143
cmd/ipfs/config.go Normal file
View File

@ -0,0 +1,143 @@
package main
import (
"errors"
"fmt"
"io"
"os"
"os/exec"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
config "github.com/jbenet/go-ipfs/config"
u "github.com/jbenet/go-ipfs/util"
)
var cmdIpfsConfig = &commander.Command{
UsageLine: "config",
Short: "Get/Set ipfs config values",
Long: `ipfs config [<key>] [<value>] - Get/Set ipfs config values.
ipfs config <key> - Get value of <key>
ipfs config <key> <value> - Set value of <key> to <value>
ipfs config --show - Show config file
ipfs config --edit - Edit config file in $EDITOR
Examples:
Get the value of the 'datastore.path' key:
ipfs config datastore.path
Set the value of the 'datastore.path' key:
ipfs config datastore.path ~/.go-ipfs/datastore
`,
Run: configCmd,
Flag: *flag.NewFlagSet("ipfs-config", flag.ExitOnError),
}
func init() {
cmdIpfsConfig.Flag.Bool("edit", false, "Edit config file in $EDITOR")
cmdIpfsConfig.Flag.Bool("show", false, "Show config file")
}
func configCmd(c *commander.Command, inp []string) error {
confdir, err := getConfigDir(c.Parent)
if err != nil {
return err
}
filename, err := config.Filename(confdir)
if err != nil {
return err
}
// if editing, open the editor
if c.Flag.Lookup("edit").Value.Get().(bool) {
return configEditor(filename)
}
// if showing, cat the file
if c.Flag.Lookup("show").Value.Get().(bool) {
return configCat(filename)
}
if len(inp) == 0 {
// "ipfs config" run without parameters
u.POut(c.Long)
return nil
}
// Getter (1 param)
if len(inp) == 1 {
value, err := config.ReadConfigKey(filename, inp[0])
if err != nil {
return fmt.Errorf("Failed to get config value: %s", err)
}
strval, ok := value.(string)
if ok {
u.POut("%s\n", strval)
return nil
}
if err := config.Encode(os.Stdout, value); err != nil {
return fmt.Errorf("Failed to encode config value: %s", err)
}
u.POut("\n")
return nil
}
// Setter (>1 params)
err = config.WriteConfigKey(filename, inp[0], inp[1])
if err != nil {
return fmt.Errorf("Failed to set config value: %s", err)
}
return nil
}
func configCat(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
if _, err = io.Copy(os.Stdout, file); err != nil {
return err
}
u.POut("\n")
return nil
}
func configEditor(filename string) error {
editor := os.Getenv("EDITOR")
if editor == "" {
return errors.New("ENV variable $EDITOR not set")
}
cmd := exec.Command("sh", "-c", editor+" "+filename)
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
return cmd.Run()
}
func writeConfig(c *commander.Command, cfg *config.Config) error {
confdir, err := getConfigDir(c)
if err != nil {
return err
}
filename, err := config.Filename(confdir)
if err != nil {
return err
}
return config.WriteConfigFile(filename, cfg)
}

32
cmd/ipfs/diag.go Normal file
View File

@ -0,0 +1,32 @@
package main
import (
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
"github.com/jbenet/go-ipfs/core/commands"
)
var cmdIpfsDiag = &commander.Command{
UsageLine: "net-diag",
Short: "Generate a diagnostics report",
Long: `ipfs net-diag - Generate a diagnostics report.
Sends out a message to each node in the network recursively
requesting a listing of data about them including number of
connected peers and latencies between them.
`,
Run: diagCmd,
Flag: *flag.NewFlagSet("ipfs-net-diag", flag.ExitOnError),
}
func init() {
cmdIpfsDiag.Flag.Bool("raw", false, "print raw json output")
}
var diagCmd = makeCommand(command{
name: "diag",
args: 0,
flags: []string{"raw"},
cmdFn: commands.Diag,
})

6
cmd/ipfs/equinox.yaml Normal file
View File

@ -0,0 +1,6 @@
---
equinox-account: CHANGEME
equinox-secret: CHANGEME
equinox-app: CHANGEME
channel: stable
private-key: equinox-priv

72
cmd/ipfs/gen.go Normal file
View File

@ -0,0 +1,72 @@
package main
import (
"fmt"
"os"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
"github.com/jbenet/go-ipfs/core/commands"
"github.com/jbenet/go-ipfs/daemon"
u "github.com/jbenet/go-ipfs/util"
)
// command is the descriptor of an ipfs daemon command.
// Used with makeCommand to proxy over commands via the daemon.
type command struct {
name string
args int
flags []string
online bool
cmdFn commands.CmdFunc
argFilter func(string) (string, error)
}
// commanderFunc is a function that can be passed into the Commander library as
// a command handler. Defined here because commander lacks this definition.
type commanderFunc func(*commander.Command, []string) error
// makeCommand Wraps a commands.CmdFunc so that it may be safely run by the
// commander library
func makeCommand(cmdDesc command) commanderFunc {
return func(c *commander.Command, inp []string) error {
if len(inp) < cmdDesc.args {
u.POut(c.Long)
return nil
}
confdir, err := getConfigDir(c)
if err != nil {
return err
}
cmd := daemon.NewCommand()
cmd.Command = cmdDesc.name
if cmdDesc.argFilter != nil {
for _, a := range inp {
s, err := cmdDesc.argFilter(a)
if err != nil {
return err
}
cmd.Args = append(cmd.Args, s)
}
} else {
cmd.Args = inp
}
for _, a := range cmdDesc.flags {
cmd.Opts[a] = c.Flag.Lookup(a).Value.Get()
}
err = daemon.SendCommand(cmd, confdir)
if err != nil {
log.Info("Executing command locally: %s", err)
// Do locally
n, err := localNode(confdir, cmdDesc.online)
if err != nil {
return fmt.Errorf("Local node creation failed: %v", err)
}
return cmdDesc.cmdFn(n, cmd.Args, cmd.Opts, os.Stdout)
}
return nil
}
}

150
cmd/ipfs/init.go Normal file
View File

@ -0,0 +1,150 @@
package main
import (
"encoding/base64"
"errors"
"os"
"path/filepath"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
config "github.com/jbenet/go-ipfs/config"
ci "github.com/jbenet/go-ipfs/crypto"
peer "github.com/jbenet/go-ipfs/peer"
updates "github.com/jbenet/go-ipfs/updates"
u "github.com/jbenet/go-ipfs/util"
)
var cmdIpfsInit = &commander.Command{
UsageLine: "init",
Short: "Initialize ipfs local configuration",
Long: `ipfs init
Initializes ipfs configuration files and generates a
new keypair.
`,
Run: initCmd,
Flag: *flag.NewFlagSet("ipfs-init", flag.ExitOnError),
}
func init() {
cmdIpfsInit.Flag.Int("b", 4096, "number of bits for keypair")
cmdIpfsInit.Flag.String("p", "", "passphrase for encrypting keys")
cmdIpfsInit.Flag.Bool("f", false, "force overwrite of existing config")
cmdIpfsInit.Flag.String("d", "", "Change default datastore location")
}
func initCmd(c *commander.Command, inp []string) error {
configpath, err := getConfigDir(c.Parent)
if err != nil {
return err
}
u.POut("initializing ipfs node at %s\n", configpath)
filename, err := config.Filename(configpath)
if err != nil {
return errors.New("Couldn't get home directory path")
}
dspath, ok := c.Flag.Lookup("d").Value.Get().(string)
if !ok {
return errors.New("failed to parse datastore flag")
}
fi, err := os.Lstat(filename)
force, ok := c.Flag.Lookup("f").Value.Get().(bool)
if !ok {
return errors.New("failed to parse force flag")
}
if fi != nil || (err != nil && !os.IsNotExist(err)) {
if !force {
return errors.New("ipfs configuration file already exists!\nReinitializing would overwrite your keys.\n(use -f to force overwrite)")
}
}
cfg := new(config.Config)
cfg.Datastore = config.Datastore{}
if len(dspath) == 0 {
dspath, err = config.DataStorePath("")
if err != nil {
return err
}
}
cfg.Datastore.Path = dspath
cfg.Datastore.Type = "leveldb"
// Construct the data store if missing
if err := os.MkdirAll(dspath, os.ModePerm); err != nil {
return err
}
// Check the directory is writeable
if f, err := os.Create(filepath.Join(dspath, "._check_writeable")); err == nil {
os.Remove(f.Name())
} else {
return errors.New("Datastore '" + dspath + "' is not writeable")
}
cfg.Identity = config.Identity{}
// setup the node addresses.
cfg.Addresses = config.Addresses{
Swarm: "/ip4/0.0.0.0/tcp/4001",
API: "/ip4/127.0.0.1/tcp/5001",
}
// setup the node mount points.
cfg.Mounts = config.Mounts{
IPFS: "/ipfs",
IPNS: "/ipns",
}
nbits, ok := c.Flag.Lookup("b").Value.Get().(int)
if !ok {
return errors.New("failed to get bits flag")
}
if nbits < 1024 {
return errors.New("Bitsize less than 1024 is considered unsafe.")
}
u.POut("generating key pair\n")
sk, pk, err := ci.GenerateKeyPair(ci.RSA, nbits)
if err != nil {
return err
}
// currently storing key unencrypted. in the future we need to encrypt it.
// TODO(security)
skbytes, err := sk.Bytes()
if err != nil {
return err
}
cfg.Identity.PrivKey = base64.StdEncoding.EncodeToString(skbytes)
id, err := peer.IDFromPubKey(pk)
if err != nil {
return err
}
cfg.Identity.PeerID = id.Pretty()
// Use these hardcoded bootstrap peers for now.
cfg.Bootstrap = []*config.BootstrapPeer{
&config.BootstrapPeer{
// mars.i.ipfs.io
PeerID: "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
Address: "/ip4/104.131.131.82/tcp/4001",
},
}
// tracking ipfs version used to generate the init folder and adding update checker default setting.
cfg.Version = config.Version{
Check: "error",
Current: updates.Version,
}
err = config.WriteConfigFile(filename, cfg)
if err != nil {
return err
}
return nil
}

220
cmd/ipfs/ipfs.go Normal file
View File

@ -0,0 +1,220 @@
package main
import (
"errors"
"fmt"
"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"
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
}
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:])
if err != nil {
if len(err.Error()) > 0 {
fmt.Fprintf(os.Stderr, "ipfs %s: %v\n", os.Args[1], err)
}
os.Exit(1)
}
return
}
// localNode constructs a node
func localNode(confdir string, online bool) (*core.IpfsNode, error) {
filename, err := config.Filename(confdir)
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
}
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
}
// 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 {
}
cc.configDir, err = getConfigDir(rootCmd)
if err != nil {
return
}
cc.node, err = localNode(cc.configDir, online)
if err != nil {
return
}
cc.daemon, err = setupDaemon(cc.configDir, cc.node)
if err != nil {
return
}
return
}
// 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")
}
maddr, err := ma.NewMultiaddr(node.Config.Addresses.API)
if err != nil {
return nil, err
}
dl, err := daemon.NewDaemonListener(node, maddr, confdir)
if err != nil {
return nil, err
}
go dl.Listen()
return dl, nil
}

29
cmd/ipfs/log.go Normal file
View File

@ -0,0 +1,29 @@
package main
import (
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"
"github.com/jbenet/go-ipfs/core/commands"
)
var cmdIpfsLog = &commander.Command{
UsageLine: "log <name> <level> ",
Short: "switch logging levels of a running daemon",
Long: `ipfs log <name> <level> - switch logging levels of a running daemon
<name> is a the subsystem logging identifier. Use * for all subsystems.
<level> is one of: debug, info, notice, warning, error, critical
ipfs log is a utility command used to change the logging output of a running daemon.
`,
Run: logCmd,
Flag: *flag.NewFlagSet("ipfs-log", flag.ExitOnError),
}
var logCmd = makeCommand(command{
name: "log",
args: 2,
flags: nil,
online: true,
cmdFn: commands.Log,
})

29
cmd/ipfs/ls.go Normal file
View File

@ -0,0 +1,29 @@
package main
import (
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
"github.com/jbenet/go-ipfs/core/commands"
)
var cmdIpfsLs = &commander.Command{
UsageLine: "ls",
Short: "List links from an object.",
Long: `ipfs ls <ipfs-path> - List links from an object.
Retrieves the object named by <ipfs-path> and displays the links
it contains, with the following format:
<link base58 hash> <link size in bytes> <link name>
`,
Run: lsCmd,
Flag: *flag.NewFlagSet("ipfs-ls", flag.ExitOnError),
}
var lsCmd = makeCommand(command{
name: "ls",
args: 1,
flags: nil,
cmdFn: commands.Ls,
})

94
cmd/ipfs/mount_unix.go Normal file
View File

@ -0,0 +1,94 @@
// +build linux darwin freebsd
package main
import (
"fmt"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
core "github.com/jbenet/go-ipfs/core"
ipns "github.com/jbenet/go-ipfs/fuse/ipns"
rofs "github.com/jbenet/go-ipfs/fuse/readonly"
)
var cmdIpfsMount = &commander.Command{
UsageLine: "mount",
Short: "Mount an ipfs read-only mountpoint.",
Long: `ipfs mount <os-path> - Mount an ipfs read-only mountpoint.
Mount ipfs at a read-only mountpoint on the OS. All ipfs objects
will be accessible under that directory. Note that the root will
not be listable, as it is virtual. Accessing known paths directly.
`,
Run: mountCmd,
Flag: *flag.NewFlagSet("ipfs-mount", flag.ExitOnError),
}
func init() {
cmdIpfsMount.Flag.String("f", "", "specify a mountpoint for ipfs")
cmdIpfsMount.Flag.String("n", "", "specify a mountpoint for ipns")
}
func mountCmd(c *commander.Command, inp []string) error {
cc, err := setupCmdContext(c, true)
if err != nil {
return err
}
defer cc.daemon.Close()
// update fsdir with flag.
fsdir := cc.node.Config.Mounts.IPFS
if val, ok := c.Flag.Lookup("f").Value.Get().(string); ok && val != "" {
fsdir = val
}
fsdone := mountIpfs(cc.node, fsdir)
// get default mount points
nsdir := cc.node.Config.Mounts.IPNS
if val, ok := c.Flag.Lookup("n").Value.Get().(string); ok && val != "" {
nsdir = val
}
nsdone := mountIpns(cc.node, nsdir, fsdir)
// wait till mounts are done.
err1 := <-fsdone
err2 := <-nsdone
if err1 != nil {
return err1
}
return err2
}
func mountIpfs(node *core.IpfsNode, fsdir string) <-chan error {
done := make(chan error)
fmt.Printf("mounting ipfs at %s\n", fsdir)
go func() {
err := rofs.Mount(node, fsdir)
done <- err
close(done)
}()
return done
}
func mountIpns(node *core.IpfsNode, nsdir, fsdir string) <-chan error {
if nsdir == "" {
return nil
}
done := make(chan error)
fmt.Printf("mounting ipns at %s\n", nsdir)
go func() {
err := ipns.Mount(node, nsdir, fsdir)
done <- err
close(done)
}()
return done
}

19
cmd/ipfs/mount_windows.go Normal file
View File

@ -0,0 +1,19 @@
package main
import (
"errors"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
)
var cmdIpfsMount = &commander.Command{
UsageLine: "mount",
Short: "Mount an ipfs read-only mountpoint.",
Long: `Not yet implemented on windows.`,
Run: mountCmd,
Flag: *flag.NewFlagSet("ipfs-mount", flag.ExitOnError),
}
func mountCmd(c *commander.Command, inp []string) error {
return errors.New("mount not yet implemented on windows")
}

57
cmd/ipfs/name.go Normal file
View File

@ -0,0 +1,57 @@
package main
import (
"fmt"
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"
)
var cmdIpfsName = &commander.Command{
UsageLine: "name [publish | resolve]",
Short: "ipfs namespace (ipns) tool",
Long: `ipfs name - Get/Set ipfs config values.
ipfs name publish [<name>] <ref> - Assign the <ref> to <name>
ipfs name resolve [<name>] - Resolve the <ref> value of <name>
IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In both publish
and resolve, the default value of <name> is your own identity public key.
Examples:
Publish a <ref> to your identity name:
> ipfs name publish QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
Publish a <ref> to another public key:
> ipfs name publish QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
Resolve the value of your identity:
> ipfs name resolve
QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
Resolve te value of another name:
> ipfs name resolve QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
`,
Run: nameCmd,
Flag: *flag.NewFlagSet("ipfs-name", flag.ExitOnError),
Subcommands: []*commander.Command{
cmdIpfsPub,
cmdIpfsResolve,
},
}
func nameCmd(c *commander.Command, args []string) error {
fmt.Println(c.Long)
return nil
}

112
cmd/ipfs/objects.go Normal file
View File

@ -0,0 +1,112 @@
package main
import (
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"
"github.com/jbenet/go-ipfs/core/commands"
)
var cmdIpfsObject = &commander.Command{
UsageLine: "object",
Short: "interact with ipfs objects",
Long: `ipfs object - interact with ipfs objects
ipfs object data <key> - return the data for this key as raw bytes
ipfs object links <key> - lists (the keys of ?) the links this key points to
ipfs object get <key> - output dag object to stdout
ipfs object put - add dag object from stdin
ipfs object is a plumbing command used to manipulate dag objects directly.
- <key> is a base58 encoded multihash.
- It reads from stdin or writes to stdout.
- It accepts multiple encodings: --encoding=[ protobuf, json, ... ]`,
Subcommands: []*commander.Command{
cmdIpfsObjectData,
cmdIpfsObjectLinks,
cmdIpfsObjectGet,
cmdIpfsObjectPut,
},
Flag: *flag.NewFlagSet("ipfs-object", flag.ExitOnError),
}
var cmdIpfsObjectData = &commander.Command{
UsageLine: "data <key>",
Short: "data outputs the raw bytes named by <key>",
Long: `ipfs data <key> - data outputs the raw bytes named by <key>
ipfs data is a plumbing command for retreiving the raw bytes stored in a dag node.
It outputs to stdout, and <key> is a base58 encoded multihash.`,
Run: makeCommand(command{
name: "objectData",
args: 1,
flags: nil,
online: true,
cmdFn: commands.ObjectData,
}),
}
var cmdIpfsObjectLinks = &commander.Command{
UsageLine: "links <key>",
Short: "outputs the links pointed to by <key>",
Long: `ipfs links <key> - outputs the links pointed to by <key>
ipfs block get is a plumbing command for retreiving raw ipfs blocks.
It outputs to stdout, and <key> is a base58 encoded multihash.`,
Run: makeCommand(command{
name: "objectLinks",
args: 1,
flags: nil,
online: true,
cmdFn: commands.ObjectLinks,
}),
}
func init() {
cmdIpfsObjectGet.Flag.String("encoding", "json", "the encoding to use..")
cmdIpfsObjectPut.Flag.String("encoding", "json", "the encoding to use..")
}
var cmdIpfsObjectGet = &commander.Command{
UsageLine: "get <key>",
Short: "get and serialize the dag node named by <key>",
Long: `ipfs get <key> - get and output the dag node named by <key>
ipfs object get is a plumbing command for retreiving dag nodes.
It serialize the dag node to the format specified by the format flag.
It outputs to stdout, and <key> is a base58 encoded multihash.
Formats:
This command outputs and accepts data in a variety of encodings: protobuf, json, etc.
Use the --encoding flag
`,
Run: makeCommand(command{
name: "blockGet",
args: 1,
flags: []string{"encoding"},
online: true,
cmdFn: commands.ObjectGet,
}),
}
var cmdIpfsObjectPut = &commander.Command{
UsageLine: "put",
Short: "store stdin as a dag object, outputs <key>",
Long: `ipfs put - store stdin as a dag object, outputs <key>
ipfs object put is a plumbing command for storing dag nodes.
It serialize the dag node to the format specified by the format flag.
It reads from stding, and <key> is a base58 encoded multihash.
Formats:
This command outputs and accepts data in a variety of encodings: protobuf, json, etc.
Use the --encoding flag`,
Run: makeCommand(command{
name: "blockPut",
args: 0,
flags: []string{"encoding"},
online: true,
cmdFn: commands.ObjectPut,
}),
}

62
cmd/ipfs/pin.go Normal file
View File

@ -0,0 +1,62 @@
package main
import (
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
"github.com/jbenet/go-ipfs/core/commands"
)
var cmdIpfsPin = &commander.Command{
UsageLine: "pin",
Short: "",
Long: `ipfs pin [add|rm] - object pinning commands
`,
Subcommands: []*commander.Command{
cmdIpfsSubPin,
cmdIpfsSubUnpin,
},
}
var cmdIpfsSubPin = &commander.Command{
UsageLine: "add",
Short: "pin an ipfs object to local storage.",
Long: `ipfs pin add <ipfs-path> - pin ipfs object to local storage.
Retrieves the object named by <ipfs-path> and stores it locally
on disk.
`,
Run: pinSubCmd,
Flag: *flag.NewFlagSet("ipfs-pin", flag.ExitOnError),
}
var pinSubCmd = makeCommand(command{
name: "pin",
args: 1,
flags: []string{"r", "d"},
cmdFn: commands.Pin,
})
var cmdIpfsSubUnpin = &commander.Command{
UsageLine: "rm",
Short: "unpin an ipfs object from local storage.",
Long: `ipfs pin rm <ipfs-path> - unpin ipfs object from local storage.
Removes the pin from the given object allowing it to be garbage
collected if needed.
`,
Run: unpinSubCmd,
Flag: *flag.NewFlagSet("ipfs-unpin", flag.ExitOnError),
}
var unpinSubCmd = makeCommand(command{
name: "unpin",
args: 1,
flags: []string{"r"},
cmdFn: commands.Unpin,
})
func init() {
cmdIpfsSubPin.Flag.Bool("r", false, "pin objects recursively")
cmdIpfsSubPin.Flag.Int("d", 1, "recursive depth")
cmdIpfsSubUnpin.Flag.Bool("r", false, "unpin objects recursively")
}

41
cmd/ipfs/publish.go Normal file
View File

@ -0,0 +1,41 @@
package main
import (
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
"github.com/jbenet/go-ipfs/core/commands"
)
var cmdIpfsPub = &commander.Command{
UsageLine: "publish",
Short: "publish a <ref> to ipns.",
Long: `ipfs publish [<name>] <ref> - publish a <ref> to ipns.
IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In publish, the
default value of <name> is your own identity public key.
Examples:
Publish a <ref> to your identity name:
> ipfs name publish QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
Publish a <ref> to another public key:
> ipfs name publish QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
`,
Run: pubCmd,
Flag: *flag.NewFlagSet("ipfs-publish", flag.ExitOnError),
}
var pubCmd = makeCommand(command{
name: "publish",
args: 1,
flags: nil,
online: true,
cmdFn: commands.Publish,
})

36
cmd/ipfs/refs.go Normal file
View File

@ -0,0 +1,36 @@
package main
import (
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
commands "github.com/jbenet/go-ipfs/core/commands"
)
var cmdIpfsRefs = &commander.Command{
UsageLine: "refs",
Short: "List link hashes from an object.",
Long: `ipfs refs <ipfs-path> - List link hashes from an object..
Retrieves the object named by <ipfs-path> and displays the link
hashes it contains, with the following format:
<link base58 hash>
Note: list all refs recursively with -r.
`,
Run: refCmd,
Flag: *flag.NewFlagSet("ipfs-refs", flag.ExitOnError),
}
func init() {
cmdIpfsRefs.Flag.Bool("r", false, "recursive: list refs recursively")
cmdIpfsRefs.Flag.Bool("u", false, "unique: list each ref only once")
}
var refCmd = makeCommand(command{
name: "refs",
args: 1,
flags: []string{"r", "u"},
cmdFn: commands.Refs,
})

42
cmd/ipfs/resolve.go Normal file
View File

@ -0,0 +1,42 @@
package main
import (
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
"github.com/jbenet/go-ipfs/core/commands"
)
var cmdIpfsResolve = &commander.Command{
UsageLine: "resolve",
Short: "resolve an ipns name to a <ref>",
Long: `ipfs resolve [<name>] - Resolve an ipns name to a <ref>.
IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In resolve, the
default value of <name> is your own identity public key.
Examples:
Resolve the value of your identity:
> ipfs name resolve
QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
Resolve te value of another name:
> ipfs name resolve QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
`,
Run: resolveCmd,
Flag: *flag.NewFlagSet("ipfs-resolve", flag.ExitOnError),
}
var resolveCmd = makeCommand(command{
name: "resolve",
args: 0,
flags: nil,
online: true,
cmdFn: commands.Resolve,
})

36
cmd/ipfs/run.go Normal file
View File

@ -0,0 +1,36 @@
package main
import (
"os"
"os/signal"
"syscall"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
)
var cmdIpfsRun = &commander.Command{
UsageLine: "run",
Short: "run local ifps node.",
Long: `run a local ipfs node with no other interface.
`,
Run: runCmd,
Flag: *flag.NewFlagSet("ipfs-run", flag.ExitOnError),
}
func runCmd(c *commander.Command, inp []string) error {
cc, err := setupCmdContext(c, true)
if err != nil {
return err
}
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT,
syscall.SIGTERM, syscall.SIGQUIT)
// wait until we get a signal to exit.
<-sigc
cc.daemon.Close()
return nil
}

49
cmd/ipfs/serve.go Normal file
View File

@ -0,0 +1,49 @@
package main
import (
"fmt"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"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"
h "github.com/jbenet/go-ipfs/server/http"
)
var cmdIpfsServe = &commander.Command{
UsageLine: "serve",
Short: "Serve an interface to ipfs",
Subcommands: []*commander.Command{
cmdIpfsServeHTTP,
},
Flag: *flag.NewFlagSet("ipfs-serve", flag.ExitOnError),
}
var cmdIpfsServeHTTP = &commander.Command{
UsageLine: "http",
Short: "Serve an HTTP API",
Long: `ipfs serve http - Serve an http gateway into ipfs.`,
Run: serveHTTPCmd,
Flag: *flag.NewFlagSet("ipfs-serve-http", flag.ExitOnError),
}
func init() {
cmdIpfsServeHTTP.Flag.String("address", "/ip4/127.0.0.1/tcp/8080", "Listen Address")
}
func serveHTTPCmd(c *commander.Command, _ []string) error {
cc, err := setupCmdContext(c, true)
if err != nil {
return err
}
defer cc.daemon.Close()
address := c.Flag.Lookup("address").Value.Get().(string)
maddr, err := ma.NewMultiaddr(address)
if err != nil {
return err
}
fmt.Printf("Serving on %s\n", address)
return h.Serve(maddr, cc.node)
}

134
cmd/ipfs/tour.go Normal file
View File

@ -0,0 +1,134 @@
// +build linux darwin freebsd
package main
import (
"fmt"
config "github.com/jbenet/go-ipfs/config"
tour "github.com/jbenet/go-ipfs/tour"
commander "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
)
var cmdIpfsTour = &commander.Command{
UsageLine: "tour [<number>]",
Short: "Take the IPFS Tour.",
Long: `ipfs tour - Take the IPFS Tour.
ipfs tour [<number>] - Show tour topic. Default to current.
ipfs tour next - Show the next tour topic.
ipfs tour list - Show a list of topics.
ipfs tour restart - Restart the tour.
This is a tour that takes you through various IPFS concepts,
features, and tools to make sure you get up to speed with
IPFS very quickly. To start, run:
ipfs tour
`,
Run: tourCmd,
Subcommands: []*commander.Command{
cmdIpfsTourNext,
cmdIpfsTourList,
cmdIpfsTourRestart,
},
}
var cmdIpfsTourNext = &commander.Command{
UsageLine: "next",
Short: "Show the next IPFS Tour topic.",
Run: tourNextCmd,
}
var cmdIpfsTourList = &commander.Command{
UsageLine: "list",
Short: "Show a list of IPFS Tour topics.",
Run: tourListCmd,
}
var cmdIpfsTourRestart = &commander.Command{
UsageLine: "restart",
Short: "Restart the IPFS Tour.",
Run: tourRestartCmd,
}
func tourCmd(c *commander.Command, inp []string) error {
cfg, err := getConfig(c)
if err != nil {
return err
}
topic := tour.TopicID(cfg.Tour.Last)
if len(inp) > 0 {
topic = tour.TopicID(inp[0])
}
return tourShow(topic)
}
func tourNextCmd(c *commander.Command, _ []string) error {
cfg, err := getConfig(c)
if err != nil {
return err
}
topic := tour.NextTopic(tour.TopicID(cfg.Tour.Last))
if err := tourShow(topic); err != nil {
return err
}
// if topic didn't change (last) done
if string(topic) == cfg.Tour.Last {
return nil
}
// topic changed, not last. write it out.
cfg.Tour.Last = string(topic)
return writeConfig(c, cfg)
}
func tourListCmd(c *commander.Command, _ []string) error {
cfg, err := getConfig(c)
if err != nil {
return err
}
lastid := tour.TopicID(cfg.Tour.Last)
for _, id := range tour.IDs {
c := ' '
switch {
case id == lastid:
c = '*'
case id.LessThan(lastid):
c = '✓'
}
t := tour.Topics[id]
fmt.Printf("- %c %-5.5s %s\n", c, id, t.Title)
}
return nil
}
func tourRestartCmd(c *commander.Command, _ []string) error {
cfg, err := getConfig(c)
if err != nil {
return err
}
cfg.Tour.Last = ""
return writeConfig(c, cfg)
}
func tourShow(id tour.ID) error {
t, found := tour.Topics[id]
if !found {
return fmt.Errorf("no topic with id: %s", id)
}
fmt.Printf("Tour %s - %s\n\n%s\n", t.ID, t.Title, t.Text)
return nil
}
func lastTour(cfg *config.Config) string {
return ""
}

62
cmd/ipfs/update.go Normal file
View File

@ -0,0 +1,62 @@
package main
import (
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"
"github.com/jbenet/go-ipfs/core/commands"
)
func init() {
cmdIpfsUpdate.Flag.Bool("force", false, "force shutdown of daemon when updating")
}
var cmdIpfsUpdate = &commander.Command{
UsageLine: "update",
Short: "check for updates and apply them",
Long: `ipfs update - check for updates and apply them
ipfs update <version> - apply
ipfs update check - just check
ipfs update log - list the changelogs
ipfs update is a utility command used to check for updates and apply them.
I wont even try, @jbenet. You do this much better :)`,
Run: makeCommand(command{
name: "updateApply",
args: 0,
flags: []string{"force"},
online: true,
cmdFn: commands.UpdateApply,
}),
Subcommands: []*commander.Command{
cmdIpfsUpdateCheck,
cmdIpfsUpdateLog,
},
Flag: *flag.NewFlagSet("ipfs-update", flag.ExitOnError),
}
var cmdIpfsUpdateCheck = &commander.Command{
UsageLine: "check",
Short: "",
Long: `ipfs update check <key>`,
Run: makeCommand(command{
name: "updateCheck",
args: 0,
flags: nil,
online: false,
cmdFn: commands.UpdateCheck,
}),
}
var cmdIpfsUpdateLog = &commander.Command{
UsageLine: "log",
Short: "list the last versions and their changelog",
Long: `ipfs updage log - list the last versions and their changelog`,
Run: makeCommand(command{
name: "updateLog",
args: 0,
flags: nil,
online: false,
cmdFn: commands.UpdateCheck,
}),
}

30
cmd/ipfs/version.go Normal file
View File

@ -0,0 +1,30 @@
package main
import (
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
updates "github.com/jbenet/go-ipfs/updates"
u "github.com/jbenet/go-ipfs/util"
)
var cmdIpfsVersion = &commander.Command{
UsageLine: "version",
Short: "Show ipfs version information.",
Long: `ipfs version - Show ipfs version information.
Returns the current version of ipfs and exits.
`,
Run: versionCmd,
}
func init() {
cmdIpfsVersion.Flag.Bool("number", false, "show only the number")
}
func versionCmd(c *commander.Command, _ []string) error {
number := c.Flag.Lookup("number").Value.Get().(bool)
if !number {
u.POut("ipfs version ")
}
u.POut("%s\n", updates.Version)
return nil
}