github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/cmd/ipfs/ipfs.go (about) 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 const heapProfile = "ipfs.mprof" 21 22 // The IPFS command tree. It is an instance of `commander.Command`. 23 var CmdIpfs = &commander.Command{ 24 UsageLine: "ipfs [<flags>] <command> [<args>]", 25 Short: "global versioned p2p merkledag file system", 26 Long: `ipfs - global versioned p2p merkledag file system 27 28 Basic commands: 29 30 init Initialize ipfs local configuration. 31 add <path> Add an object to ipfs. 32 cat <ref> Show ipfs object data. 33 ls <ref> List links from an object. 34 refs <ref> List link hashes from an object. 35 36 Tool commands: 37 38 config Manage configuration. 39 update Download and apply go-ipfs updates. 40 version Show ipfs version information. 41 commands List all available commands. 42 43 Advanced Commands: 44 45 mount Mount an ipfs read-only mountpoint. 46 serve Serve an interface to ipfs. 47 net-diag Print network diagnostic 48 49 Plumbing commands: 50 51 block Interact with raw blocks in the datastore 52 object Interact with raw dag nodes 53 54 55 Use "ipfs help <command>" for more information about a command. 56 `, 57 Run: ipfsCmd, 58 Subcommands: []*commander.Command{ 59 cmdIpfsAdd, 60 cmdIpfsCat, 61 cmdIpfsLs, 62 cmdIpfsRefs, 63 cmdIpfsConfig, 64 cmdIpfsVersion, 65 cmdIpfsCommands, 66 cmdIpfsMount, 67 cmdIpfsInit, 68 cmdIpfsServe, 69 cmdIpfsRun, 70 cmdIpfsName, 71 cmdIpfsBootstrap, 72 cmdIpfsDiag, 73 cmdIpfsBlock, 74 cmdIpfsObject, 75 cmdIpfsUpdate, 76 cmdIpfsLog, 77 cmdIpfsPin, 78 cmdIpfsTour, 79 }, 80 Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError), 81 } 82 83 // log is the command logger 84 var log = u.Logger("cmd/ipfs") 85 86 func init() { 87 config, err := config.PathRoot() 88 if err != nil { 89 fmt.Fprintln(os.Stderr, "Failure initializing the default Config Directory: ", err) 90 os.Exit(1) 91 } 92 CmdIpfs.Flag.String("c", config, "specify config directory") 93 } 94 95 func ipfsCmd(c *commander.Command, args []string) error { 96 u.POut(c.Long) 97 return nil 98 } 99 100 func main() { 101 // if debugging, setup profiling. 102 if u.Debug { 103 ofi, err := os.Create("cpu.prof") 104 defer ofi.Close() 105 106 if err != nil { 107 fmt.Println(err) 108 return 109 } 110 111 pprof.StartCPUProfile(ofi) 112 defer pprof.StopCPUProfile() 113 } 114 115 err := CmdIpfs.Dispatch(os.Args[1:]) 116 if err != nil { 117 if len(err.Error()) > 0 { 118 fmt.Fprintf(os.Stderr, "ipfs %s: %v\n", os.Args[1], err) 119 } 120 os.Exit(1) 121 } 122 123 if u.Debug { 124 err := writeHeapProfileToFile() 125 if err != nil { 126 log.Critical(err) 127 } 128 } 129 return 130 } 131 132 // localNode constructs a node 133 func localNode(confdir string, online bool) (*core.IpfsNode, error) { 134 filename, err := config.Filename(confdir) 135 if err != nil { 136 return nil, err 137 } 138 139 cfg, err := config.Load(filename) 140 if err != nil { 141 return nil, err 142 } 143 144 if err := updates.CliCheckForUpdates(cfg, filename); err != nil { 145 return nil, err 146 } 147 148 return core.NewIpfsNode(cfg, online) 149 } 150 151 // Gets the config "-c" flag from the command, or returns 152 // the default configuration root directory 153 func getConfigDir(c *commander.Command) (string, error) { 154 155 // use the root cmd (that's where config is specified) 156 for ; c.Parent != nil; c = c.Parent { 157 } 158 159 // flag should be defined on root. 160 param := c.Flag.Lookup("c").Value.Get().(string) 161 if param != "" { 162 return u.TildeExpansion(param) 163 } 164 165 return config.PathRoot() 166 } 167 168 func getConfig(c *commander.Command) (*config.Config, error) { 169 confdir, err := getConfigDir(c) 170 if err != nil { 171 return nil, err 172 } 173 174 filename, err := config.Filename(confdir) 175 if err != nil { 176 return nil, err 177 } 178 179 return config.Load(filename) 180 } 181 182 // cmdContext is a wrapper structure that keeps a node, a daemonlistener, and 183 // a config directory together. These three are needed for most commands. 184 type cmdContext struct { 185 node *core.IpfsNode 186 daemon *daemon.DaemonListener 187 configDir string 188 } 189 190 // setupCmdContext initializes a cmdContext structure from a given command. 191 func setupCmdContext(c *commander.Command, online bool) (cc cmdContext, err error) { 192 rootCmd := c 193 for ; rootCmd.Parent != nil; rootCmd = rootCmd.Parent { 194 } 195 196 cc.configDir, err = getConfigDir(rootCmd) 197 if err != nil { 198 return 199 } 200 201 cc.node, err = localNode(cc.configDir, online) 202 if err != nil { 203 return 204 } 205 206 cc.daemon, err = setupDaemon(cc.configDir, cc.node) 207 if err != nil { 208 return 209 } 210 211 return 212 } 213 214 // setupDaemon sets up the daemon corresponding to given node. 215 func setupDaemon(confdir string, node *core.IpfsNode) (*daemon.DaemonListener, error) { 216 if node.Config.Addresses.API == "" { 217 return nil, errors.New("no config.Addresses.API endpoint supplied") 218 } 219 220 maddr, err := ma.NewMultiaddr(node.Config.Addresses.API) 221 if err != nil { 222 return nil, err 223 } 224 225 dl, err := daemon.NewDaemonListener(node, maddr, confdir) 226 if err != nil { 227 return nil, err 228 } 229 go dl.Listen() 230 return dl, nil 231 } 232 233 func writeHeapProfileToFile() error { 234 mprof, err := os.Create(heapProfile) 235 if err != nil { 236 log.Fatal(err) 237 } 238 defer mprof.Close() 239 return pprof.WriteHeapProfile(mprof) 240 }