github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/cmd/ipfs/ipfs.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  
     6  	cmds "github.com/ipfs/go-ipfs/commands"
     7  	commands "github.com/ipfs/go-ipfs/core/commands"
     8  )
     9  
    10  // This is the CLI root, used for executing commands accessible to CLI clients.
    11  // Some subcommands (like 'ipfs daemon' or 'ipfs init') are only accessible here,
    12  // and can't be called through the HTTP API.
    13  var Root = &cmds.Command{
    14  	Options:  commands.Root.Options,
    15  	Helptext: commands.Root.Helptext,
    16  }
    17  
    18  // commandsClientCmd is the "ipfs commands" command for local cli
    19  var commandsClientCmd = commands.CommandsCmd(Root)
    20  
    21  // Commands in localCommands should always be run locally (even if daemon is running).
    22  // They can override subcommands in commands.Root by defining a subcommand with the same name.
    23  var localCommands = map[string]*cmds.Command{
    24  	"daemon":   daemonCmd,
    25  	"init":     initCmd,
    26  	"commands": commandsClientCmd,
    27  }
    28  var localMap = make(map[*cmds.Command]bool)
    29  
    30  func init() {
    31  	// setting here instead of in literal to prevent initialization loop
    32  	// (some commands make references to Root)
    33  	Root.Subcommands = localCommands
    34  
    35  	// copy all subcommands from commands.Root into this root (if they aren't already present)
    36  	for k, v := range commands.Root.Subcommands {
    37  		if _, found := Root.Subcommands[k]; !found {
    38  			Root.Subcommands[k] = v
    39  		}
    40  	}
    41  
    42  	for _, v := range localCommands {
    43  		localMap[v] = true
    44  	}
    45  }
    46  
    47  // isLocal returns true if the command should only be run locally (not sent to daemon), otherwise false
    48  func isLocal(cmd *cmds.Command) bool {
    49  	_, found := localMap[cmd]
    50  	return found
    51  }
    52  
    53  // NB: when necessary, properties are described using negatives in order to
    54  // provide desirable defaults
    55  type cmdDetails struct {
    56  	cannotRunOnClient bool
    57  	cannotRunOnDaemon bool
    58  	doesNotUseRepo    bool
    59  
    60  	// doesNotUseConfigAsInput describes commands that do not use the config as
    61  	// input. These commands either initialize the config or perform operations
    62  	// that don't require access to the config.
    63  	//
    64  	// pre-command hooks that require configs must not be run before these
    65  	// commands.
    66  	doesNotUseConfigAsInput bool
    67  
    68  	// preemptsAutoUpdate describes commands that must be executed without the
    69  	// auto-update pre-command hook
    70  	preemptsAutoUpdate bool
    71  }
    72  
    73  func (d *cmdDetails) String() string {
    74  	return fmt.Sprintf("on client? %t, on daemon? %t, uses repo? %t",
    75  		d.canRunOnClient(), d.canRunOnDaemon(), d.usesRepo())
    76  }
    77  
    78  func (d *cmdDetails) Loggable() map[string]interface{} {
    79  	return map[string]interface{}{
    80  		"canRunOnClient":     d.canRunOnClient(),
    81  		"canRunOnDaemon":     d.canRunOnDaemon(),
    82  		"preemptsAutoUpdate": d.preemptsAutoUpdate,
    83  		"usesConfigAsInput":  d.usesConfigAsInput(),
    84  		"usesRepo":           d.usesRepo(),
    85  	}
    86  }
    87  
    88  func (d *cmdDetails) usesConfigAsInput() bool        { return !d.doesNotUseConfigAsInput }
    89  func (d *cmdDetails) doesNotPreemptAutoUpdate() bool { return !d.preemptsAutoUpdate }
    90  func (d *cmdDetails) canRunOnClient() bool           { return !d.cannotRunOnClient }
    91  func (d *cmdDetails) canRunOnDaemon() bool           { return !d.cannotRunOnDaemon }
    92  func (d *cmdDetails) usesRepo() bool                 { return !d.doesNotUseRepo }
    93  
    94  // "What is this madness!?" you ask. Our commands have the unfortunate problem of
    95  // not being able to run on all the same contexts. This map describes these
    96  // properties so that other code can make decisions about whether to invoke a
    97  // command or return an error to the user.
    98  var cmdDetailsMap = map[*cmds.Command]cmdDetails{
    99  	initCmd: {doesNotUseConfigAsInput: true, cannotRunOnDaemon: true, doesNotUseRepo: true},
   100  
   101  	// daemonCmd allows user to initialize the config. Thus, it may be called
   102  	// without using the config as input
   103  	daemonCmd:                  {doesNotUseConfigAsInput: true, cannotRunOnDaemon: true},
   104  	commandsClientCmd:          {doesNotUseRepo: true},
   105  	commands.CommandsDaemonCmd: {doesNotUseRepo: true},
   106  	commands.DiagCmd:           {cannotRunOnClient: true},
   107  	commands.VersionCmd:        {doesNotUseConfigAsInput: true, doesNotUseRepo: true}, // must be permitted to run before init
   108  	commands.UpdateCmd:         {preemptsAutoUpdate: true, cannotRunOnDaemon: true},
   109  	commands.UpdateCheckCmd:    {preemptsAutoUpdate: true},
   110  	commands.UpdateLogCmd:      {preemptsAutoUpdate: true},
   111  	commands.LogCmd:            {cannotRunOnClient: true},
   112  }