Avoid resolving executable() until requested at runtime

This is to avoid hitting the filesystem and resolving symlinks
unnecessarily. The value of executable is just used conditionally by a
handful of commands.
This commit is contained in:
Mislav Marohnić 2021-09-24 14:42:41 +02:00
parent 78b35b7b6e
commit d853ce5bc9
7 changed files with 18 additions and 12 deletions

View file

@ -236,7 +236,7 @@ func mainRun() exitCode {
newRelease := <-updateMessageChan
if newRelease != nil {
isHomebrew := isUnderHomebrew(cmdFactory.Executable)
isHomebrew := isUnderHomebrew(cmdFactory.Executable())
if isHomebrew && isRecentRelease(newRelease.PublishedAt) {
// do not notify Homebrew users before the version bump had a chance to get merged into homebrew-core
return exitOK

View file

@ -38,8 +38,6 @@ func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Comm
IO: f.IOStreams,
Config: f.Config,
HttpClient: f.HttpClient,
MainExecutable: f.Executable,
}
var tokenStdin bool
@ -103,6 +101,7 @@ func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Comm
}
}
opts.MainExecutable = f.Executable()
if runF != nil {
return runF(opts)
}

View file

@ -147,7 +147,8 @@ func Test_NewCmdLogin(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
io, stdin, _, _ := iostreams.Test()
f := &cmdutil.Factory{
IOStreams: io,
IOStreams: io,
Executable: func() string { return "/path/to/gh" },
}
io.SetStdoutTTY(true)

View file

@ -36,7 +36,6 @@ func NewCmdRefresh(f *cmdutil.Factory, runF func(*RefreshOptions) error) *cobra.
_, err := authflow.AuthFlowWithConfig(cfg, io, hostname, "", scopes)
return err
},
MainExecutable: f.Executable,
}
cmd := &cobra.Command{
@ -62,6 +61,7 @@ func NewCmdRefresh(f *cmdutil.Factory, runF func(*RefreshOptions) error) *cobra.
return &cmdutil.FlagError{Err: errors.New("--hostname required when not running interactively")}
}
opts.MainExecutable = f.Executable()
if runF != nil {
return runF(opts)
}

View file

@ -88,7 +88,8 @@ func Test_NewCmdRefresh(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
io, _, _, _ := iostreams.Test()
f := &cmdutil.Factory{
IOStreams: io,
IOStreams: io,
Executable: func() string { return "/path/to/gh" },
}
io.SetStdinTTY(tt.tty)
io.SetStdoutTTY(tt.tty)

View file

@ -19,12 +19,17 @@ import (
)
func New(appVersion string) *cmdutil.Factory {
var exe string
f := &cmdutil.Factory{
Config: configFunc(), // No factory dependencies
Branch: branchFunc(), // No factory dependencies
Executable: executable("gh"), // No factory dependencies
ExtensionManager: extension.NewManager(),
Config: configFunc(), // No factory dependencies
Branch: branchFunc(), // No factory dependencies
Executable: func() string {
if exe != "" {
return exe
}
exe = executable("gh")
return exe
},
}
f.IOStreams = ioStreams(f) // Depends on Config

View file

@ -27,5 +27,5 @@ type Factory struct {
ExtensionManager extensions.ExtensionManager
// Executable is the path to the currently invoked gh binary
Executable string
Executable func() string
}