ipfs.go 3.75 KB
Newer Older
1 2 3
package main

import (
4 5
	"fmt"

6 7 8 9
	cmds "github.com/jbenet/go-ipfs/commands"
	commands "github.com/jbenet/go-ipfs/core/commands2"
)

10 11 12
// This is the CLI root, used for executing commands accessible to CLI clients.
// Some subcommands (like 'ipfs daemon' or 'ipfs init') are only accessible here,
// and can't be called through the HTTP API.
13
var Root = &cmds.Command{
14 15
	Options:  commands.Root.Options,
	Helptext: commands.Root.Helptext,
16 17
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
18 19 20
// commandsClientCmd is the "ipfs commands" command for local cli
var commandsClientCmd = commands.CommandsCmd(Root)

21 22 23
// Commands in localCommands should always be run locally (even if daemon is running).
// They can override subcommands in commands.Root by defining a subcommand with the same name.
var localCommands = map[string]*cmds.Command{
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
24 25 26 27
	"daemon":   daemonCmd,
	"init":     initCmd,
	"tour":     tourCmd,
	"commands": commandsClientCmd,
28
}
29
var localMap = make(map[*cmds.Command]bool)
30 31 32 33

func init() {
	// setting here instead of in literal to prevent initialization loop
	// (some commands make references to Root)
34
	Root.Subcommands = localCommands
35 36 37 38 39 40 41

	// copy all subcommands from commands.Root into this root (if they aren't already present)
	for k, v := range commands.Root.Subcommands {
		if _, found := Root.Subcommands[k]; !found {
			Root.Subcommands[k] = v
		}
	}
42 43 44 45 46 47 48 49 50 51

	for _, v := range localCommands {
		localMap[v] = true
	}
}

// isLocal returns true if the command should only be run locally (not sent to daemon), otherwise false
func isLocal(cmd *cmds.Command) bool {
	_, found := localMap[cmd]
	return found
52
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
53

54 55
// NB: when necessary, properties are described using negatives in order to
// provide desirable defaults
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
56 57 58 59
type cmdDetails struct {
	cannotRunOnClient bool
	cannotRunOnDaemon bool
	doesNotUseRepo    bool
60

61 62 63 64 65 66 67
	// doesNotUseConfigAsInput describes commands that do not use the config as
	// input. These commands either initialize the config or perform operations
	// that don't require access to the config.
	//
	// pre-command hooks that require configs must not be run before these
	// commands.
	doesNotUseConfigAsInput bool
68

Brian Tiger Chow's avatar
docs  
Brian Tiger Chow committed
69
	// preemptsAutoUpdate describes commands that must be executed without the
70
	// auto-update pre-command hook
71
	preemptsAutoUpdate bool
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
72 73
}

74 75 76 77 78
func (d *cmdDetails) String() string {
	return fmt.Sprintf("on client? %t, on daemon? %t, uses repo? %t",
		d.canRunOnClient(), d.canRunOnDaemon(), d.usesRepo())
}

79 80 81 82
func (d *cmdDetails) usesConfigAsInput() bool { return !d.doesNotUseConfigAsInput }
func (d *cmdDetails) canRunOnClient() bool    { return !d.cannotRunOnClient }
func (d *cmdDetails) canRunOnDaemon() bool    { return !d.cannotRunOnDaemon }
func (d *cmdDetails) usesRepo() bool          { return !d.doesNotUseRepo }
83

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
84 85 86 87 88
// "What is this madness!?" you ask. Our commands have the unfortunate problem of
// not being able to run on all the same contexts. This map describes these
// properties so that other code can make decisions about whether to invoke a
// command or return an error to the user.
var cmdDetailsMap = map[*cmds.Command]cmdDetails{
89
	initCmd:                    cmdDetails{doesNotUseConfigAsInput: true, cannotRunOnDaemon: true, doesNotUseRepo: true},
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
90 91 92 93
	daemonCmd:                  cmdDetails{cannotRunOnDaemon: true},
	commandsClientCmd:          cmdDetails{doesNotUseRepo: true},
	commands.CommandsDaemonCmd: cmdDetails{doesNotUseRepo: true},
	commands.DiagCmd:           cmdDetails{cannotRunOnClient: true},
94
	commands.VersionCmd:        cmdDetails{doesNotUseConfigAsInput: true, doesNotUseRepo: true}, // must be permitted to run before init
95 96 97
	commands.UpdateCmd:         cmdDetails{preemptsAutoUpdate: true, cannotRunOnDaemon: true},
	commands.UpdateCheckCmd:    cmdDetails{preemptsAutoUpdate: true},
	commands.UpdateLogCmd:      cmdDetails{preemptsAutoUpdate: true},
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
98 99
	commands.LogCmd:            cmdDetails{cannotRunOnClient: true},
}