Commit 408fadc8 authored by Brian Tiger Chow's avatar Brian Tiger Chow

fix(2/main) don't check for updates when running init

@jbenet @mappum

Yeah, there's some duplicated work. But there's also a separation of
concerns. In one case, we check to determine where the command should
run. In the other case, we check to determine which hooks should run.
Having these actions separated reduces complexity in a nice way.

License: MIT
Signed-off-by: default avatarBrian Tiger Chow <brian@perfmode.com>
parent eb5bb1da
......@@ -55,6 +55,13 @@ type cmdDetails struct {
cannotRunOnClient bool
cannotRunOnDaemon bool
doesNotUseRepo bool
// initializesConfig describes commands that initialize the config.
// pre-command hooks that require configs must not be run before this
// command
initializesConfig bool
preemptsUpdates bool
}
func (d *cmdDetails) String() string {
......@@ -71,14 +78,14 @@ func (d *cmdDetails) usesRepo() bool { return !d.doesNotUseRepo }
// 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{
initCmd: cmdDetails{cannotRunOnDaemon: true, doesNotUseRepo: true},
initCmd: cmdDetails{initializesConfig: true, cannotRunOnDaemon: true, doesNotUseRepo: true},
daemonCmd: cmdDetails{cannotRunOnDaemon: true},
commandsClientCmd: cmdDetails{doesNotUseRepo: true},
commands.CommandsDaemonCmd: cmdDetails{doesNotUseRepo: true},
commands.DiagCmd: cmdDetails{cannotRunOnClient: true},
commands.VersionCmd: cmdDetails{doesNotUseRepo: true},
commands.UpdateCmd: cmdDetails{cannotRunOnDaemon: true},
commands.UpdateCheckCmd: cmdDetails{},
commands.UpdateLogCmd: cmdDetails{},
commands.UpdateCmd: cmdDetails{preemptsUpdates: true, cannotRunOnDaemon: true},
commands.UpdateCheckCmd: cmdDetails{preemptsUpdates: true},
commands.UpdateLogCmd: cmdDetails{preemptsUpdates: true},
commands.LogCmd: cmdDetails{cannotRunOnClient: true},
}
......@@ -20,6 +20,7 @@ import (
daemon "github.com/jbenet/go-ipfs/daemon2"
updates "github.com/jbenet/go-ipfs/updates"
u "github.com/jbenet/go-ipfs/util"
"github.com/jbenet/go-ipfs/util/debugerror"
)
// log is the command logger
......@@ -201,21 +202,61 @@ func (i *cmdInvocation) requestedHelp() (short bool, long bool, err error) {
return longHelp, shortHelp, nil
}
func callPreCommandHooks(details cmdDetails, req cmds.Request, root *cmds.Command) error {
log.Debug("Calling pre-command hooks...")
// some hooks only run when the command is executed locally
daemon, err := commandShouldRunOnDaemon(details, req, root)
if err != nil {
return err
}
// check for updates when 1) commands is going to be run locally, 2) the
// command does not initialize the config, and 3) the command does not
// pre-empt updates
if !daemon && !details.initializesConfig && !details.preemptsUpdates {
log.Debug("Calling hook: Check for updates")
cfg, err := req.Context().GetConfig()
if err != nil {
return err
}
// Check for updates and potentially install one.
if err := updates.CliCheckForUpdates(cfg, req.Context().ConfigRoot); err != nil {
return err
}
}
return nil
}
func callCommand(req cmds.Request, root *cmds.Command) (cmds.Response, error) {
var res cmds.Response
useDaemon, err := commandShouldRunOnDaemon(req, root)
details, err := commandDetails(req.Path(), root)
if err != nil {
return nil, err
}
cfg, err := req.Context().GetConfig()
useDaemon, err := commandShouldRunOnDaemon(*details, req, root)
if err != nil {
return nil, err
}
err = callPreCommandHooks(*details, req, root)
if err != nil {
return nil, err
}
if useDaemon {
cfg, err := req.Context().GetConfig()
if err != nil {
return nil, err
}
addr, err := ma.NewMultiaddr(cfg.Addresses.API)
if err != nil {
return nil, err
......@@ -237,11 +278,6 @@ func callCommand(req cmds.Request, root *cmds.Command) (cmds.Response, error) {
} else {
log.Info("Executing command locally")
// Check for updates and potentially install one.
if err := updates.CliCheckForUpdates(cfg, req.Context().ConfigRoot); err != nil {
return nil, err
}
// this sets up the function that will initialize the node
// this is so that we can construct the node lazily.
ctx := req.Context()
......@@ -267,13 +303,11 @@ func callCommand(req cmds.Request, root *cmds.Command) (cmds.Response, error) {
return res, nil
}
func commandShouldRunOnDaemon(req cmds.Request, root *cmds.Command) (bool, error) {
path := req.Path()
// root command.
if len(path) < 1 {
return false, nil
}
// commandDetails returns a command's details for the command given by |path|
// within the |root| command tree.
//
// Returns an error if the command is not found in the Command tree.
func commandDetails(path []string, root *cmds.Command) (*cmdDetails, error) {
var details cmdDetails
// find the last command in path that has a cmdDetailsMap entry
cmd := root
......@@ -281,7 +315,7 @@ func commandShouldRunOnDaemon(req cmds.Request, root *cmds.Command) (bool, error
var found bool
cmd, found = cmd.Subcommands[cmp]
if !found {
return false, fmt.Errorf("subcommand %s should be in root", cmp)
return nil, debugerror.Errorf("subcommand %s should be in root", cmp)
}
if cmdDetails, found := cmdDetailsMap[cmd]; found {
......@@ -289,6 +323,21 @@ func commandShouldRunOnDaemon(req cmds.Request, root *cmds.Command) (bool, error
}
}
log.Debugf("cmd perms for +%v: %s", path, details.String())
return &details, nil
}
// commandShouldRunOnDaemon determines, from commmand details, whether a
// command ought to be executed on an IPFS daemon.
//
// It returns true if the command should be executed on a daemon and false if
// it should be executed on a client. It returns an error if the command must
// NOT be executed on either.
func commandShouldRunOnDaemon(details cmdDetails, req cmds.Request, root *cmds.Command) (bool, error) {
path := req.Path()
// root command.
if len(path) < 1 {
return false, nil
}
if details.cannotRunOnClient && details.cannotRunOnDaemon {
return false, fmt.Errorf("command disabled: %s", path[0])
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment