ipfs.go 4.11 KB
Newer Older
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
1 2 3
package main

import (
4
	"errors"
Juan Batiz-Benet's avatar
refmt  
Juan Batiz-Benet committed
5
	"fmt"
6
	"os"
7
	"runtime/pprof"
8

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
9 10
	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"
11
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
12 13

	config "github.com/jbenet/go-ipfs/config"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
14
	core "github.com/jbenet/go-ipfs/core"
15
	daemon "github.com/jbenet/go-ipfs/daemon"
Juan Batiz-Benet's avatar
refmt  
Juan Batiz-Benet committed
16
	u "github.com/jbenet/go-ipfs/util"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
17 18
)

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
19
// The IPFS command tree. It is an instance of `commander.Command`.
Juan Batiz-Benet's avatar
refmt  
Juan Batiz-Benet committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33
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:

    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:

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
34 35 36
    config        Manage configuration.
    version       Show ipfs version information.
    commands      List all available commands.
Juan Batiz-Benet's avatar
refmt  
Juan Batiz-Benet committed
37 38 39

Advanced Commands:

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
40
    mount         Mount an ipfs read-only mountpoint.
41
    serve         Serve an interface to ipfs.
Juan Batiz-Benet's avatar
refmt  
Juan Batiz-Benet committed
42 43 44 45 46

Use "ipfs help <command>" for more information about a command.
`,
	Run: ipfsCmd,
	Subcommands: []*commander.Command{
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
47
		cmdIpfsAdd,
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
48
		cmdIpfsCat,
49
		cmdIpfsLs,
Juan Batiz-Benet's avatar
refs  
Juan Batiz-Benet committed
50
		cmdIpfsRefs,
51
		cmdIpfsConfig,
Juan Batiz-Benet's avatar
refmt  
Juan Batiz-Benet committed
52 53
		cmdIpfsVersion,
		cmdIpfsCommands,
54
		cmdIpfsMount,
55
		cmdIpfsInit,
verokarhu's avatar
verokarhu committed
56
		cmdIpfsServe,
Jeromy's avatar
Jeromy committed
57
		cmdIpfsRun,
58
		cmdIpfsPub,
59
		cmdIpfsResolve,
Juan Batiz-Benet's avatar
refmt  
Juan Batiz-Benet committed
60 61 62 63
	},
	Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
}

Jeromy's avatar
Jeromy committed
64
func init() {
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
65
	config, err := config.PathRoot()
66 67 68 69
	if err != nil {
		config = ""
	}
	CmdIpfs.Flag.String("c", config, "specify config directory")
Jeromy's avatar
Jeromy committed
70 71
}

Juan Batiz-Benet's avatar
refmt  
Juan Batiz-Benet committed
72 73 74 75 76
func ipfsCmd(c *commander.Command, args []string) error {
	u.POut(c.Long)
	return nil
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
77
func main() {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
	u.Debug = false

	// setup logging
	u.SetupLogging()

	// 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()
93
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
94 95

	err := CmdIpfs.Dispatch(os.Args[1:])
Juan Batiz-Benet's avatar
refmt  
Juan Batiz-Benet committed
96 97
	if err != nil {
		if len(err.Error()) > 0 {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
98
			fmt.Fprintf(os.Stderr, "ipfs %s: %v\n", os.Args[1], err)
Juan Batiz-Benet's avatar
refmt  
Juan Batiz-Benet committed
99 100 101 102
		}
		os.Exit(1)
	}
	return
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
103
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
104

105
// localNode constructs a node
106
func localNode(confdir string, online bool) (*core.IpfsNode, error) {
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
107
	filename, err := config.Filename(confdir)
108 109 110 111 112
	if err != nil {
		return nil, err
	}

	cfg, err := config.Load(filename)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
113 114 115 116
	if err != nil {
		return nil, err
	}

117
	return core.NewIpfsNode(cfg, online)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
118
}
Jeromy's avatar
Jeromy committed
119 120

// Gets the config "-c" flag from the command, or returns
121
// the default configuration root directory
122
func getConfigDir(c *commander.Command) (string, error) {
Jeromy's avatar
Jeromy committed
123
	conf := c.Flag.Lookup("c").Value.Get()
124
	if conf == nil {
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
125
		return config.PathRoot()
126
	}
Jeromy's avatar
Jeromy committed
127
	confStr, ok := conf.(string)
128
	if !ok {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
129
		return "", errors.New("failed to retrieve config flag value")
Jeromy's avatar
Jeromy committed
130
	}
131
	if len(confStr) == 0 {
Shanti Bouchez-Mongardé's avatar
Shanti Bouchez-Mongardé committed
132
		return config.PathRoot()
133
	}
134 135

	return u.TildeExpansion(confStr)
Jeromy's avatar
Jeromy committed
136
}
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183

// 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) {
	cc.configDir, err = getConfigDir(c.Parent.Parent)
	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
}