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 }