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  }