diff --git a/go.mod b/go.mod index 0149feda5..81b248c47 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/integrii/flaggy v1.4.0 github.com/iriri/minimal/gitignore v0.3.2 // indirect github.com/jesseduffield/go-git/v5 v5.1.2-0.20201006095850-341962be15a4 - github.com/jesseduffield/gocui v0.3.1-0.20211017220056-b2fc03c74a6f + github.com/jesseduffield/gocui v0.3.1-0.20211024041248-681a61c53ed0 github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e github.com/jesseduffield/yaml v2.1.0+incompatible github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 @@ -43,7 +43,7 @@ require ( github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c // indirect - golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 // indirect + golang.org/x/sys v0.0.0-20211023085530-d6a326fbbf70 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect gopkg.in/ozeidan/fuzzy-patricia.v3 v3.0.0 diff --git a/go.sum b/go.sum index 1d3c41de1..c7bdb6337 100644 --- a/go.sum +++ b/go.sum @@ -84,6 +84,8 @@ github.com/jesseduffield/gocui v0.3.1-0.20211017091015-8bf4a4666b77 h1:MQUxSxVBT github.com/jesseduffield/gocui v0.3.1-0.20211017091015-8bf4a4666b77/go.mod h1:znJuCDnF2Ph40YZSlBwdX/4GEofnIoWLGdT4mK5zRAU= github.com/jesseduffield/gocui v0.3.1-0.20211017220056-b2fc03c74a6f h1:JHrb78pj+gYC3KiJKL1WW6lYzlatBIF46oREn68plTM= github.com/jesseduffield/gocui v0.3.1-0.20211017220056-b2fc03c74a6f/go.mod h1:znJuCDnF2Ph40YZSlBwdX/4GEofnIoWLGdT4mK5zRAU= +github.com/jesseduffield/gocui v0.3.1-0.20211024041248-681a61c53ed0 h1:To4mMbu6oQpbbyHa4WtMTc/DHa9dqiRWZpDLMNK+Hdk= +github.com/jesseduffield/gocui v0.3.1-0.20211024041248-681a61c53ed0/go.mod h1:znJuCDnF2Ph40YZSlBwdX/4GEofnIoWLGdT4mK5zRAU= github.com/jesseduffield/minimal v0.0.0-20211018110810-9cde264e6b1e h1:WZc73tBVMMhcO6zXyZBItLEF4jgBpBH0lFCZzDgrjDg= github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e h1:uw/oo+kg7t/oeMs6sqlAwr85ND/9cpO3up3VxphxY0U= github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e/go.mod h1:u60qdFGXRd36jyEXxetz0vQceQIxzI13lIo3EFUDf4I= @@ -195,6 +197,8 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 h1:KzbpndAYEM+4oHRp9JmB2ewj0NHHxO3Z0g7Gus2O1kk= golang.org/x/sys v0.0.0-20211015200801-69063c4bb744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211023085530-d6a326fbbf70 h1:SeSEfdIxyvwGJliREIJhRPPXvW6sDlLT+UQ3B0hD0NA= +golang.org/x/sys v0.0.0-20211023085530-d6a326fbbf70/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/pkg/app/app.go b/pkg/app/app.go index bb7485cca..f24af6e58 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -127,7 +127,13 @@ func NewApp(config config.AppConfigurer, filterPath string) (*App, error) { return app, err } - app.GitCommand, err = commands.NewGitCommand(app.Log, app.OSCommand, app.Tr, app.Config, git_config.NewStdCachedGitConfig(app.Log)) + app.GitCommand, err = commands.NewGitCommand( + app.Log, + app.OSCommand, + app.Tr, + app.Config, + git_config.NewStdCachedGitConfig(app.Log), + ) if err != nil { return app, err } diff --git a/pkg/commands/dummies.go b/pkg/commands/dummies.go index a8178385d..ba052fe9b 100644 --- a/pkg/commands/dummies.go +++ b/pkg/commands/dummies.go @@ -1,6 +1,9 @@ package commands import ( + "io" + "io/ioutil" + "github.com/jesseduffield/lazygit/pkg/commands/git_config" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/config" @@ -17,10 +20,11 @@ func NewDummyGitCommand() *GitCommand { func NewDummyGitCommandWithOSCommand(osCommand *oscommands.OSCommand) *GitCommand { newAppConfig := config.NewDummyAppConfig() return &GitCommand{ - Log: utils.NewDummyLog(), - OSCommand: osCommand, - Tr: i18n.NewTranslationSet(utils.NewDummyLog(), newAppConfig.GetUserConfig().Gui.Language), - Config: newAppConfig, - GitConfig: git_config.NewFakeGitConfig(map[string]string{}), + Log: utils.NewDummyLog(), + OSCommand: osCommand, + Tr: i18n.NewTranslationSet(utils.NewDummyLog(), newAppConfig.GetUserConfig().Gui.Language), + Config: newAppConfig, + GitConfig: git_config.NewFakeGitConfig(map[string]string{}), + GetCmdWriter: func() io.Writer { return ioutil.Discard }, } } diff --git a/pkg/commands/git.go b/pkg/commands/git.go index a1a925de7..8750ecf51 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -1,6 +1,7 @@ package commands import ( + "io" "io/ioutil" "os" "path/filepath" @@ -40,6 +41,11 @@ type GitCommand struct { // Push to current determines whether the user has configured to push to the remote branch of the same name as the current or not PushToCurrent bool + + // this is just a view that we write to when running certain commands. + // Coincidentally at the moment it's the same view that OnRunCommand logs to + // but that need not always be the case. + GetCmdWriter func() io.Writer } // NewGitCommand it runs git commands @@ -77,6 +83,7 @@ func NewGitCommand( DotGitDir: dotGitDir, PushToCurrent: pushToCurrent, GitConfig: gitConfig, + GetCmdWriter: func() io.Writer { return ioutil.Discard }, } gitCommand.PatchManager = patch.NewPatchManager(log, gitCommand.ApplyPatch, gitCommand.ShowFileDiff) diff --git a/pkg/commands/oscommands/exec_live.go b/pkg/commands/oscommands/exec_live.go new file mode 100644 index 000000000..6ca70a5ec --- /dev/null +++ b/pkg/commands/oscommands/exec_live.go @@ -0,0 +1,153 @@ +package oscommands + +import ( + "bufio" + "bytes" + "io" + "os/exec" + "regexp" + "strings" + "unicode/utf8" + + "github.com/go-errors/errors" + "github.com/jesseduffield/lazygit/pkg/utils" +) + +// DetectUnamePass detect a username / password / passphrase question in a command +// promptUserForCredential is a function that gets executed when this function detect you need to fillin a password or passphrase +// The promptUserForCredential argument will be "username", "password" or "passphrase" and expects the user's password/passphrase or username back +func (c *OSCommand) DetectUnamePass(cmdObj ICmdObj, writer io.Writer, promptUserForCredential func(string) string) error { + ttyText := "" + errMessage := c.RunCommandWithOutputLive(cmdObj, writer, func(word string) string { + ttyText = ttyText + " " + word + + prompts := map[string]string{ + `.+'s password:`: "password", + `Password\s*for\s*'.+':`: "password", + `Username\s*for\s*'.+':`: "username", + `Enter\s*passphrase\s*for\s*key\s*'.+':`: "passphrase", + } + + for pattern, askFor := range prompts { + if match, _ := regexp.MatchString(pattern, ttyText); match { + ttyText = "" + return promptUserForCredential(askFor) + } + } + + return "" + }) + return errMessage +} + +// Due to a lack of pty support on windows we have RunCommandWithOutputLiveWrapper being defined +// separate for windows and other OS's +func (c *OSCommand) RunCommandWithOutputLive(cmdObj ICmdObj, writer io.Writer, handleOutput func(string) string) error { + return RunCommandWithOutputLiveWrapper(c, cmdObj, writer, handleOutput) +} + +type cmdHandler struct { + stdoutPipe io.Reader + stdinPipe io.Writer + close func() error +} + +// RunCommandWithOutputLiveAux runs a command and return every word that gets written in stdout +// Output is a function that executes by every word that gets read by bufio +// As return of output you need to give a string that will be written to stdin +// NOTE: If the return data is empty it won't write anything to stdin +func RunCommandWithOutputLiveAux( + c *OSCommand, + cmdObj ICmdObj, + writer io.Writer, + // handleOutput takes a word from stdout and returns a string to be written to stdin. + // See DetectUnamePass above for how this is used to check for a username/password request + handleOutput func(string) string, + startCmd func(cmd *exec.Cmd) (*cmdHandler, error), +) error { + c.Log.WithField("command", cmdObj.ToString()).Info("RunCommand") + c.LogCommand(cmdObj.ToString(), true) + cmd := cmdObj.AddEnvVars("LANG=en_US.UTF-8", "LC_ALL=en_US.UTF-8").GetCmd() + + var stderr bytes.Buffer + cmd.Stderr = io.MultiWriter(writer, &stderr) + + handler, err := startCmd(cmd) + if err != nil { + return err + } + + defer func() { + if closeErr := handler.close(); closeErr != nil { + c.Log.Error(closeErr) + } + }() + + tr := io.TeeReader(handler.stdoutPipe, writer) + + go utils.Safe(func() { + scanner := bufio.NewScanner(tr) + scanner.Split(scanWordsWithNewLines) + for scanner.Scan() { + text := scanner.Text() + output := strings.Trim(text, " ") + toInput := handleOutput(output) + if toInput != "" { + _, _ = handler.stdinPipe.Write([]byte(toInput)) + } + } + }) + + err = cmd.Wait() + if err != nil { + return errors.New(stderr.String()) + } + + return nil +} + +// scanWordsWithNewLines is a copy of bufio.ScanWords but this also captures new lines +// For specific comments about this function take a look at: bufio.ScanWords +func scanWordsWithNewLines(data []byte, atEOF bool) (advance int, token []byte, err error) { + start := 0 + for width := 0; start < len(data); start += width { + var r rune + r, width = utf8.DecodeRune(data[start:]) + if !isSpace(r) { + break + } + } + for width, i := 0, start; i < len(data); i += width { + var r rune + r, width = utf8.DecodeRune(data[i:]) + if isSpace(r) { + return i + width, data[start:i], nil + } + } + if atEOF && len(data) > start { + return len(data), data[start:], nil + } + return start, nil, nil +} + +// isSpace is also copied from the bufio package and has been modified to also captures new lines +// For specific comments about this function take a look at: bufio.isSpace +func isSpace(r rune) bool { + if r <= '\u00FF' { + switch r { + case ' ', '\t', '\v', '\f': + return true + case '\u0085', '\u00A0': + return true + } + return false + } + if '\u2000' <= r && r <= '\u200a' { + return true + } + switch r { + case '\u1680', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000': + return true + } + return false +} diff --git a/pkg/commands/oscommands/exec_live_default.go b/pkg/commands/oscommands/exec_live_default.go index 95d5d09fb..827db9ed3 100644 --- a/pkg/commands/oscommands/exec_live_default.go +++ b/pkg/commands/oscommands/exec_live_default.go @@ -4,95 +4,34 @@ package oscommands import ( - "bufio" - "bytes" - "strings" - "unicode/utf8" - - "github.com/go-errors/errors" - "github.com/jesseduffield/lazygit/pkg/utils" + "io" + "os/exec" "github.com/creack/pty" ) -// RunCommandWithOutputLiveWrapper runs a command and return every word that gets written in stdout -// Output is a function that executes by every word that gets read by bufio -// As return of output you need to give a string that will be written to stdin -// NOTE: If the return data is empty it won't written anything to stdin -func RunCommandWithOutputLiveWrapper(c *OSCommand, cmdObj ICmdObj, output func(string) string) error { - c.Log.WithField("command", cmdObj.ToString()).Info("RunCommand") - c.LogCommand(cmdObj.ToString(), true) - cmd := cmdObj.AddEnvVars("LANG=en_US.UTF-8", "LC_ALL=en_US.UTF-8").GetCmd() +func RunCommandWithOutputLiveWrapper( + c *OSCommand, + cmdObj ICmdObj, + writer io.Writer, + output func(string) string, +) error { + return RunCommandWithOutputLiveAux( + c, + cmdObj, + writer, + output, + func(cmd *exec.Cmd) (*cmdHandler, error) { + ptmx, err := pty.Start(cmd) + if err != nil { + return nil, err + } - var stderr bytes.Buffer - cmd.Stderr = &stderr - - ptmx, err := pty.Start(cmd) - - if err != nil { - return err - } - - go utils.Safe(func() { - scanner := bufio.NewScanner(ptmx) - scanner.Split(scanWordsWithNewLines) - for scanner.Scan() { - toOutput := strings.Trim(scanner.Text(), " ") - _, _ = ptmx.WriteString(output(toOutput)) - } - }) - - err = cmd.Wait() - ptmx.Close() - if err != nil { - return errors.New(stderr.String()) - } - - return nil -} - -// scanWordsWithNewLines is a copy of bufio.ScanWords but this also captures new lines -// For specific comments about this function take a look at: bufio.ScanWords -func scanWordsWithNewLines(data []byte, atEOF bool) (advance int, token []byte, err error) { - start := 0 - for width := 0; start < len(data); start += width { - var r rune - r, width = utf8.DecodeRune(data[start:]) - if !isSpace(r) { - break - } - } - for width, i := 0, start; i < len(data); i += width { - var r rune - r, width = utf8.DecodeRune(data[i:]) - if isSpace(r) { - return i + width, data[start:i], nil - } - } - if atEOF && len(data) > start { - return len(data), data[start:], nil - } - return start, nil, nil -} - -// isSpace is also copied from the bufio package and has been modified to also captures new lines -// For specific comments about this function take a look at: bufio.isSpace -func isSpace(r rune) bool { - if r <= '\u00FF' { - switch r { - case ' ', '\t', '\v', '\f': - return true - case '\u0085', '\u00A0': - return true - } - return false - } - if '\u2000' <= r && r <= '\u200a' { - return true - } - switch r { - case '\u1680', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000': - return true - } - return false + return &cmdHandler{ + stdoutPipe: ptmx, + stdinPipe: ptmx, + close: ptmx.Close, + }, nil + }, + ) } diff --git a/pkg/commands/oscommands/exec_live_win.go b/pkg/commands/oscommands/exec_live_win.go index aa17242e3..5b61e478b 100644 --- a/pkg/commands/oscommands/exec_live_win.go +++ b/pkg/commands/oscommands/exec_live_win.go @@ -3,8 +3,61 @@ package oscommands -// RunCommandWithOutputLiveWrapper runs a command live but because of windows compatibility this command can't be ran there -// TODO: Remove this hack and replace it with a proper way to run commands live on windows -func RunCommandWithOutputLiveWrapper(c *OSCommand, cmdObj ICmdObj, output func(string) string) error { - return c.RunCommand(cmdObj.ToString()) +import ( + "bytes" + "io" + "os/exec" + "sync" +) + +type Buffer struct { + b bytes.Buffer + m sync.Mutex +} + +func (b *Buffer) Read(p []byte) (n int, err error) { + b.m.Lock() + defer b.m.Unlock() + return b.b.Read(p) +} +func (b *Buffer) Write(p []byte) (n int, err error) { + b.m.Lock() + defer b.m.Unlock() + return b.b.Write(p) +} + +// RunCommandWithOutputLiveWrapper runs a command live but because of windows compatibility this command can't be ran there +// TODO: Remove this hack and replace it with a proper way to run commands live on windows. We still have an issue where if a password is requested, the request for a password is written straight to stdout because we can't control the stdout of a subprocess of a subprocess. Keep an eye on https://github.com/creack/pty/pull/109 +func RunCommandWithOutputLiveWrapper( + c *OSCommand, + cmdObj ICmdObj, + writer io.Writer, + output func(string) string, +) error { + return RunCommandWithOutputLiveAux( + c, + cmdObj, + writer, + output, + func(cmd *exec.Cmd) (*cmdHandler, error) { + stdoutReader, stdoutWriter := io.Pipe() + cmd.Stdout = stdoutWriter + + buf := &Buffer{} + cmd.Stdin = buf + + if err := cmd.Start(); err != nil { + return nil, err + } + + // because we don't yet have windows support for a pty, we instead just + // pass our standard stream handlers and because there's no pty to close + // we pass a no-op function for that. + return &cmdHandler{ + stdoutPipe: stdoutReader, + stdinPipe: buf, + close: func() error { return nil }, + }, nil + }, + ) } diff --git a/pkg/commands/oscommands/os.go b/pkg/commands/oscommands/os.go index f0c9525a5..cb41edff4 100644 --- a/pkg/commands/oscommands/os.go +++ b/pkg/commands/oscommands/os.go @@ -7,7 +7,6 @@ import ( "os" "os/exec" "path/filepath" - "regexp" "strings" "sync" @@ -217,38 +216,6 @@ func (c *OSCommand) ShellCommandFromString(commandStr string) *exec.Cmd { return c.ExecutableFromString(shellCommand) } -// RunCommandWithOutputLive runs RunCommandWithOutputLiveWrapper -func (c *OSCommand) RunCommandWithOutputLive(cmdObj ICmdObj, output func(string) string) error { - return RunCommandWithOutputLiveWrapper(c, cmdObj, output) -} - -// DetectUnamePass detect a username / password / passphrase question in a command -// promptUserForCredential is a function that gets executed when this function detect you need to fillin a password or passphrase -// The promptUserForCredential argument will be "username", "password" or "passphrase" and expects the user's password/passphrase or username back -func (c *OSCommand) DetectUnamePass(cmdObj ICmdObj, promptUserForCredential func(string) string) error { - ttyText := "" - errMessage := c.RunCommandWithOutputLive(cmdObj, func(word string) string { - ttyText = ttyText + " " + word - - prompts := map[string]string{ - `.+'s password:`: "password", - `Password\s*for\s*'.+':`: "password", - `Username\s*for\s*'.+':`: "username", - `Enter\s*passphrase\s*for\s*key\s*'.+':`: "passphrase", - } - - for pattern, askFor := range prompts { - if match, _ := regexp.MatchString(pattern, ttyText); match { - ttyText = "" - return promptUserForCredential(askFor) - } - } - - return "" - }) - return errMessage -} - // RunCommand runs a command and just returns the error func (c *OSCommand) RunCommand(formatString string, formatArgs ...interface{}) error { _, err := c.RunCommandWithOutput(formatString, formatArgs...) diff --git a/pkg/commands/remotes.go b/pkg/commands/remotes.go index 0839f9583..11e5dc26f 100644 --- a/pkg/commands/remotes.go +++ b/pkg/commands/remotes.go @@ -2,6 +2,8 @@ package commands import ( "fmt" + + "github.com/jesseduffield/lazygit/pkg/commands/oscommands" ) func (c *GitCommand) AddRemote(name string, url string) error { @@ -23,7 +25,11 @@ func (c *GitCommand) UpdateRemoteUrl(remoteName string, updatedUrl string) error func (c *GitCommand) DeleteRemoteBranch(remoteName string, branchName string, promptUserForCredential func(string) string) error { command := fmt.Sprintf("git push %s --delete %s", c.OSCommand.Quote(remoteName), c.OSCommand.Quote(branchName)) cmdObj := c.NewCmdObjFromStr(command) - return c.OSCommand.DetectUnamePass(cmdObj, promptUserForCredential) + return c.DetectUnamePass(cmdObj, promptUserForCredential) +} + +func (c *GitCommand) DetectUnamePass(cmdObj oscommands.ICmdObj, promptUserForCredential func(string) string) error { + return c.OSCommand.DetectUnamePass(cmdObj, c.GetCmdWriter(), promptUserForCredential) } // CheckRemoteBranchExists Returns remote branch diff --git a/pkg/commands/sync.go b/pkg/commands/sync.go index 3f94c5f4e..35f258f4b 100644 --- a/pkg/commands/sync.go +++ b/pkg/commands/sync.go @@ -38,7 +38,7 @@ func (c *GitCommand) Push(opts PushOpts) error { } cmdObj := c.NewCmdObjFromStr(cmdStr) - return c.OSCommand.DetectUnamePass(cmdObj, opts.PromptUserForCredential) + return c.DetectUnamePass(cmdObj, opts.PromptUserForCredential) } type FetchOptions struct { @@ -59,7 +59,7 @@ func (c *GitCommand) Fetch(opts FetchOptions) error { } cmdObj := c.NewCmdObjFromStr(cmdStr) - return c.OSCommand.DetectUnamePass(cmdObj, func(question string) string { + return c.DetectUnamePass(cmdObj, func(question string) string { if opts.PromptUserForCredential != nil { return opts.PromptUserForCredential(question) } @@ -95,17 +95,17 @@ func (c *GitCommand) Pull(opts PullOptions) error { // setting GIT_SEQUENCE_EDITOR to ':' as a way of skipping it, in case the user // has 'pull.rebase = interactive' configured. cmdObj := c.NewCmdObjFromStr(cmdStr).AddEnvVars("GIT_SEQUENCE_EDITOR=:") - return c.OSCommand.DetectUnamePass(cmdObj, opts.PromptUserForCredential) + return c.DetectUnamePass(cmdObj, opts.PromptUserForCredential) } func (c *GitCommand) FastForward(branchName string, remoteName string, remoteBranchName string, promptUserForCredential func(string) string) error { cmdStr := fmt.Sprintf("git fetch %s %s:%s", c.OSCommand.Quote(remoteName), c.OSCommand.Quote(remoteBranchName), c.OSCommand.Quote(branchName)) cmdObj := c.NewCmdObjFromStr(cmdStr) - return c.OSCommand.DetectUnamePass(cmdObj, promptUserForCredential) + return c.DetectUnamePass(cmdObj, promptUserForCredential) } func (c *GitCommand) FetchRemote(remoteName string, promptUserForCredential func(string) string) error { cmdStr := fmt.Sprintf("git fetch %s", c.OSCommand.Quote(remoteName)) cmdObj := c.NewCmdObjFromStr(cmdStr) - return c.OSCommand.DetectUnamePass(cmdObj, promptUserForCredential) + return c.DetectUnamePass(cmdObj, promptUserForCredential) } diff --git a/pkg/commands/tags.go b/pkg/commands/tags.go index af40ae603..9aa327dd3 100644 --- a/pkg/commands/tags.go +++ b/pkg/commands/tags.go @@ -15,5 +15,5 @@ func (c *GitCommand) DeleteTag(tagName string) error { func (c *GitCommand) PushTag(remoteName string, tagName string, promptUserForCredential func(string) string) error { cmdStr := fmt.Sprintf("git push %s %s", c.OSCommand.Quote(remoteName), c.OSCommand.Quote(tagName)) cmdObj := c.NewCmdObjFromStr(cmdStr) - return c.OSCommand.DetectUnamePass(cmdObj, promptUserForCredential) + return c.DetectUnamePass(cmdObj, promptUserForCredential) } diff --git a/pkg/gui/commit_message_panel.go b/pkg/gui/commit_message_panel.go index 7ed9669ab..edc86eff7 100644 --- a/pkg/gui/commit_message_panel.go +++ b/pkg/gui/commit_message_panel.go @@ -22,9 +22,9 @@ func (gui *Gui) handleCommitConfirm() error { cmdStr := gui.GitCommand.CommitCmdStr(message, flags) gui.OnRunCommand(oscommands.NewCmdLogEntry(cmdStr, gui.Tr.Spans.Commit, true)) + _ = gui.returnFromContext() return gui.withGpgHandling(cmdStr, gui.Tr.CommittingStatus, func() error { gui.Views.CommitMessage.ClearTextArea() - _ = gui.returnFromContext() return nil }) } diff --git a/pkg/gui/extras_panel.go b/pkg/gui/extras_panel.go index ee106223e..7d68bb1ec 100644 --- a/pkg/gui/extras_panel.go +++ b/pkg/gui/extras_panel.go @@ -1,5 +1,11 @@ package gui +import ( + "io" + + "github.com/jesseduffield/lazygit/pkg/gui/style" +) + func (gui *Gui) handleCreateExtrasMenuPanel() error { menuItems := []*menuItem{ { @@ -48,3 +54,28 @@ func (gui *Gui) scrollDownExtra() error { return nil } + +func (gui *Gui) getCmdWriter() io.Writer { + return &prefixWriter{writer: gui.Views.Extras, prefix: style.FgMagenta.Sprintf("\n\n%s\n", gui.Tr.GitOutput)} +} + +// Ensures that the first write is preceded by writing a prefix. +// This allows us to say 'Git output:' before writing the actual git output. +// We could just write directly to the view in this package before running the command but we already have code in the commands package that writes to the same view beforehand (with the command it's about to run) so things would be out of order. +type prefixWriter struct { + prefix string + prefixWritten bool + writer io.Writer +} + +func (self *prefixWriter) Write(p []byte) (n int, err error) { + if !self.prefixWritten { + self.prefixWritten = true + // assuming we can write this prefix in one go + _, err = self.writer.Write([]byte(self.prefix)) + if err != nil { + return + } + } + return self.writer.Write(p) +} diff --git a/pkg/gui/gpg.go b/pkg/gui/gpg.go index e172f3720..1811e4fb5 100644 --- a/pkg/gui/gpg.go +++ b/pkg/gui/gpg.go @@ -1,5 +1,11 @@ package gui +import ( + "fmt" + + "github.com/jesseduffield/lazygit/pkg/gui/style" +) + // Currently there is a bug where if we switch to a subprocess from within // WithWaitingStatus we get stuck there and can't return to lazygit. We could // fix this bug, or just stop running subprocesses from within there, given that @@ -19,23 +25,38 @@ func (gui *Gui) withGpgHandling(cmdStr string, waitingStatus string, onSuccess f return err } - if err != nil { - return err - } + return err } else { - return gui.WithWaitingStatus(waitingStatus, func() error { - err := gui.OSCommand.RunCommand(cmdStr) - if err != nil { - return err - } else if onSuccess != nil { - if err := onSuccess(); err != nil { - return err - } - } - - return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) - }) + return gui.RunAndStream(cmdStr, waitingStatus, onSuccess) } - - return nil +} + +func (gui *Gui) RunAndStream(cmdStr string, waitingStatus string, onSuccess func() error) error { + return gui.WithWaitingStatus(waitingStatus, func() error { + cmd := gui.OSCommand.ShellCommandFromString(cmdStr) + cmd.Env = append(cmd.Env, "TERM=dumb") + cmdWriter := gui.getCmdWriter() + cmd.Stdout = cmdWriter + cmd.Stderr = cmdWriter + + if err := cmd.Run(); err != nil { + if _, err := cmd.Stdout.Write([]byte(fmt.Sprintf("%s\n", style.FgRed.Sprint(err.Error())))); err != nil { + gui.Log.Error(err) + } + _ = gui.refreshSidePanels(refreshOptions{mode: ASYNC}) + return gui.surfaceError( + fmt.Errorf( + gui.Tr.GitCommandFailed, gui.Config.GetUserConfig().Keybinding.Universal.ExtrasMenu, + ), + ) + } + + if onSuccess != nil { + if err := onSuccess(); err != nil { + return err + } + } + + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) + }) } diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index a7f308b7b..0c43c3f34 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -123,12 +123,15 @@ func (gui *Gui) createAllViews() error { gui.Views.Extras.FgColor = theme.GocuiDefaultTextColor gui.Views.Extras.Autoscroll = true gui.Views.Extras.Wrap = true + gui.printCommandLogHeader() if _, err := gui.g.SetCurrentView(gui.defaultSideContext().GetViewName()); err != nil { return err } + gui.GitCommand.GetCmdWriter = gui.getCmdWriter + return nil } diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 2f72c151c..ae5fab1b3 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -434,6 +434,8 @@ type TranslationSet struct { NoConfigFileFoundErr string LcLoadingFileSuggestions string MustSpecifyOriginError string + GitOutput string + GitCommandFailed string Spans Spans } @@ -961,6 +963,8 @@ func englishTranslationSet() TranslationSet { NoConfigFileFoundErr: "No config file found", LcLoadingFileSuggestions: "loading file suggestions", MustSpecifyOriginError: "Must specify a remote if specifying a branch", + GitOutput: "Git output:", + GitCommandFailed: "Git command failed. Check command log for details (open with %s)", Spans: Spans{ // TODO: combine this with the original keybinding descriptions (those are all in lowercase atm) CheckoutCommit: "Checkout commit", diff --git a/vendor/github.com/jesseduffield/gocui/escape.go b/vendor/github.com/jesseduffield/gocui/escape.go index a6c9d5769..a9739f641 100644 --- a/vendor/github.com/jesseduffield/gocui/escape.go +++ b/vendor/github.com/jesseduffield/gocui/escape.go @@ -29,12 +29,15 @@ type ( fontEffect int ) -type instruction struct { - kind int - param1 int - param2 int - toWrite []rune -} +type instruction interface{ isInstruction() } + +type eraseInLineFromCursor struct{} + +func (self eraseInLineFromCursor) isInstruction() {} + +type noInstruction struct{} + +func (self noInstruction) isInstruction() {} const ( stateNone escapeState = iota @@ -87,7 +90,7 @@ func newEscapeInterpreter(mode OutputMode) *escapeInterpreter { curFgColor: ColorDefault, curBgColor: ColorDefault, mode: mode, - instruction: instruction{kind: NONE}, + instruction: noInstruction{}, } return ei } @@ -101,7 +104,7 @@ func (ei *escapeInterpreter) reset() { } func (ei *escapeInterpreter) instructionRead() { - ei.instruction.kind = NONE + ei.instruction = noInstruction{} } // parseOne parses a rune. If isEscape is true, it means that the rune is part @@ -137,6 +140,8 @@ func (ei *escapeInterpreter) parseOne(ch rune) (isEscape bool, err error) { ei.csiParam = append(ei.csiParam, "") case ch == 'm': ei.csiParam = append(ei.csiParam, "0") + case ch == 'K': + // fall through default: return false, errCSIParseError } @@ -168,12 +173,20 @@ func (ei *escapeInterpreter) parseOne(ch rune) (isEscape bool, err error) { ei.csiParam = nil return true, nil case ch == 'K': - p, err := strconv.Atoi(ei.csiParam[0]) - if err != nil { - return false, errCSIParseError + p := 0 + if len(ei.csiParam) != 0 && ei.csiParam[0] != "" { + p, err = strconv.Atoi(ei.csiParam[0]) + if err != nil { + return false, errCSIParseError + } + } + + if p == 0 { + ei.instruction = eraseInLineFromCursor{} + } else { + // non-zero values of P not supported + ei.instruction = noInstruction{} } - ei.instruction.kind = ERASE_IN_LINE - ei.instruction.param1 = p ei.state = stateNone ei.csiParam = nil diff --git a/vendor/github.com/jesseduffield/gocui/gui.go b/vendor/github.com/jesseduffield/gocui/gui.go index 957a9fe62..3bc701299 100644 --- a/vendor/github.com/jesseduffield/gocui/gui.go +++ b/vendor/github.com/jesseduffield/gocui/gui.go @@ -1041,7 +1041,6 @@ func (g *Gui) draw(v *View) error { Screen.HideCursor() } - v.clearRunes() if err := v.draw(); err != nil { return err } diff --git a/vendor/github.com/jesseduffield/gocui/view.go b/vendor/github.com/jesseduffield/gocui/view.go index 11e0e6d70..0ebd6e4a2 100644 --- a/vendor/github.com/jesseduffield/gocui/view.go +++ b/vendor/github.com/jesseduffield/gocui/view.go @@ -359,7 +359,32 @@ func (v *View) Dimensions() (int, int, int, int) { // Size returns the number of visible columns and rows in the View. func (v *View) Size() (x, y int) { - return v.x1 - v.x0 - 1, v.y1 - v.y0 - 1 + return v.Width(), v.Height() +} + +func (v *View) Width() int { + return v.x1 - v.x0 - 1 +} + +func (v *View) Height() int { + return v.y1 - v.y0 - 1 +} + +// if a view has a frame, that leaves less space for its writeable area +func (v *View) InnerWidth() int { + return v.Width() - v.frameOffset() +} + +func (v *View) InnerHeight() int { + return v.Height() - v.frameOffset() +} + +func (v *View) frameOffset() int { + if v.Frame { + return 1 + } else { + return 0 + } } // Name returns the name of the view. @@ -576,12 +601,14 @@ func (v *View) writeRunes(p []rune) { case '\r': v.wx = 0 default: - cells := v.parseInput(r) + moveCursor, cells := v.parseInput(r) if cells == nil { continue } v.writeCells(v.wx, v.wy, cells) - v.wx += len(cells) + if moveCursor { + v.wx += len(cells) + } } } } @@ -589,8 +616,9 @@ func (v *View) writeRunes(p []rune) { // parseInput parses char by char the input written to the View. It returns nil // while processing ESC sequences. Otherwise, it returns a cell slice that // contains the processed data. -func (v *View) parseInput(ch rune) []cell { +func (v *View) parseInput(ch rune) (bool, []cell) { cells := []cell{} + moveCursor := true isEscape, err := v.ei.parseOne(ch) if err != nil { @@ -604,25 +632,32 @@ func (v *View) parseInput(ch rune) []cell { } v.ei.reset() } else { - if isEscape { - return nil - } repeatCount := 1 - if ch == '\t' { + if _, ok := v.ei.instruction.(eraseInLineFromCursor); ok { + // fill rest of line + v.ei.instructionRead() + repeatCount = v.InnerWidth() - v.wx + ch = ' ' + moveCursor = false + } else if isEscape { + // do not output anything + return moveCursor, nil + } else if ch == '\t' { + // fill tab-sized space ch = ' ' repeatCount = 4 } + c := cell{ + fgColor: v.ei.curFgColor, + bgColor: v.ei.curBgColor, + chr: ch, + } for i := 0; i < repeatCount; i++ { - c := cell{ - fgColor: v.ei.curFgColor, - bgColor: v.ei.curBgColor, - chr: ch, - } cells = append(cells, c) } } - return cells + return moveCursor, cells } // Read reads data into p from the current reading position set by SetReadPos. @@ -767,6 +802,8 @@ func (v *View) IsTainted() bool { // draw re-draws the view's contents. func (v *View) draw() error { + v.clearRunes() + if !v.Visible { return nil } @@ -809,8 +846,9 @@ func (v *View) draw() error { } } - if v.Autoscroll && len(v.viewLines) > maxY { - v.oy = len(v.viewLines) - maxY + visibleViewLinesHeight := v.viewLineLengthIgnoringTrailingBlankLines() + if v.Autoscroll && visibleViewLinesHeight > maxY { + v.oy = visibleViewLinesHeight - maxY } y := 0 for i, vline := range v.viewLines { @@ -858,6 +896,18 @@ func (v *View) draw() error { return nil } +// if autoscroll is enabled but we only have a single row of cells shown to the +// user, we don't want to scroll to the final line if it contains no text. So +// this tells us the view lines height when we ignore any trailing blank lines +func (v *View) viewLineLengthIgnoringTrailingBlankLines() int { + for i := len(v.viewLines) - 1; i >= 0; i-- { + if len(v.viewLines[i].line) > 0 { + return i + 1 + } + } + return 0 +} + func (v *View) isPatternMatchedRune(x, y int) (bool, bool) { searchStringLength := len(v.searcher.searchString) for i, pos := range v.searcher.searchPositions { @@ -1008,23 +1058,6 @@ func indexFunc(r rune) bool { return r == ' ' || r == 0 } -// SetLine changes the contents of an existing line. -func (v *View) SetLine(y int, text string) error { - if y < 0 || y >= len(v.lines) { - err := ErrInvalidPoint - return err - } - - v.tainted = true - line := make([]cell, 0) - for _, r := range text { - c := v.parseInput(r) - line = append(line, c...) - } - v.lines[y] = line - return nil -} - // SetHighlight toggles highlighting of separate lines, for custom lists // or multiple selection in views. func (v *View) SetHighlight(y int, on bool) error { @@ -1129,14 +1162,10 @@ func (v *View) RenderTextArea() { fmt.Fprint(v, v.TextArea.GetContent()) cursorX, cursorY := v.TextArea.GetCursorXY() prevOriginX, prevOriginY := v.Origin() - width, height := v.Size() + width, height := v.InnerWidth(), v.InnerHeight() - frameAdjustment := 0 - if v.Frame { - frameAdjustment = -1 - } - newViewCursorX, newOriginX := updatedCursorAndOrigin(prevOriginX, width+frameAdjustment, cursorX) - newViewCursorY, newOriginY := updatedCursorAndOrigin(prevOriginY, height+frameAdjustment, cursorY) + newViewCursorX, newOriginX := updatedCursorAndOrigin(prevOriginX, width, cursorX) + newViewCursorY, newOriginY := updatedCursorAndOrigin(prevOriginY, height, cursorY) _ = v.SetCursor(newViewCursorX, newViewCursorY) _ = v.SetOrigin(newOriginX, newOriginY) diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_linux.go b/vendor/golang.org/x/sys/unix/sockcmsg_linux.go index 8bf457059..e86d543b9 100644 --- a/vendor/golang.org/x/sys/unix/sockcmsg_linux.go +++ b/vendor/golang.org/x/sys/unix/sockcmsg_linux.go @@ -34,3 +34,25 @@ func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) { ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0])) return &ucred, nil } + +// PktInfo4 encodes Inet4Pktinfo into a socket control message of type IP_PKTINFO. +func PktInfo4(info *Inet4Pktinfo) []byte { + b := make([]byte, CmsgSpace(SizeofInet4Pktinfo)) + h := (*Cmsghdr)(unsafe.Pointer(&b[0])) + h.Level = SOL_IP + h.Type = IP_PKTINFO + h.SetLen(CmsgLen(SizeofInet4Pktinfo)) + *(*Inet4Pktinfo)(h.data(0)) = *info + return b +} + +// PktInfo6 encodes Inet6Pktinfo into a socket control message of type IPV6_PKTINFO. +func PktInfo6(info *Inet6Pktinfo) []byte { + b := make([]byte, CmsgSpace(SizeofInet6Pktinfo)) + h := (*Cmsghdr)(unsafe.Pointer(&b[0])) + h.Level = SOL_IPV6 + h.Type = IPV6_PKTINFO + h.SetLen(CmsgLen(SizeofInet6Pktinfo)) + *(*Inet6Pktinfo)(h.data(0)) = *info + return b +} diff --git a/vendor/golang.org/x/sys/windows/aliases.go b/vendor/golang.org/x/sys/windows/aliases.go index af3af60db..a20ebea63 100644 --- a/vendor/golang.org/x/sys/windows/aliases.go +++ b/vendor/golang.org/x/sys/windows/aliases.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build windows -// +build go1.9 +//go:build windows && go1.9 +// +build windows,go1.9 package windows diff --git a/vendor/golang.org/x/sys/windows/eventlog.go b/vendor/golang.org/x/sys/windows/eventlog.go index 40af946e1..2cd60645e 100644 --- a/vendor/golang.org/x/sys/windows/eventlog.go +++ b/vendor/golang.org/x/sys/windows/eventlog.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package windows diff --git a/vendor/golang.org/x/sys/windows/mksyscall.go b/vendor/golang.org/x/sys/windows/mksyscall.go index 328e3b2ac..610291098 100644 --- a/vendor/golang.org/x/sys/windows/mksyscall.go +++ b/vendor/golang.org/x/sys/windows/mksyscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build generate // +build generate package windows diff --git a/vendor/golang.org/x/sys/windows/race.go b/vendor/golang.org/x/sys/windows/race.go index a74e3e24b..9196b089c 100644 --- a/vendor/golang.org/x/sys/windows/race.go +++ b/vendor/golang.org/x/sys/windows/race.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows && race // +build windows,race package windows diff --git a/vendor/golang.org/x/sys/windows/race0.go b/vendor/golang.org/x/sys/windows/race0.go index e44a3cbf6..7bae4817a 100644 --- a/vendor/golang.org/x/sys/windows/race0.go +++ b/vendor/golang.org/x/sys/windows/race0.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows && !race // +build windows,!race package windows diff --git a/vendor/golang.org/x/sys/windows/service.go b/vendor/golang.org/x/sys/windows/service.go index b269850d0..5b28ae168 100644 --- a/vendor/golang.org/x/sys/windows/service.go +++ b/vendor/golang.org/x/sys/windows/service.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package windows @@ -235,3 +236,4 @@ type QUERY_SERVICE_LOCK_STATUS struct { //sys NotifyServiceStatusChange(service Handle, notifyMask uint32, notifier *SERVICE_NOTIFY) (ret error) = advapi32.NotifyServiceStatusChangeW //sys SubscribeServiceChangeNotifications(service Handle, eventType uint32, callback uintptr, callbackCtx uintptr, subscription *uintptr) (ret error) = sechost.SubscribeServiceChangeNotifications? //sys UnsubscribeServiceChangeNotifications(subscription uintptr) = sechost.UnsubscribeServiceChangeNotifications? +//sys RegisterServiceCtrlHandlerEx(serviceName *uint16, handlerProc uintptr, context uintptr) (handle Handle, err error) = advapi32.RegisterServiceCtrlHandlerExW diff --git a/vendor/golang.org/x/sys/windows/str.go b/vendor/golang.org/x/sys/windows/str.go index 917cc2aae..4fc01434e 100644 --- a/vendor/golang.org/x/sys/windows/str.go +++ b/vendor/golang.org/x/sys/windows/str.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package windows diff --git a/vendor/golang.org/x/sys/windows/syscall.go b/vendor/golang.org/x/sys/windows/syscall.go index 6122f557a..72074d582 100644 --- a/vendor/golang.org/x/sys/windows/syscall.go +++ b/vendor/golang.org/x/sys/windows/syscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows // Package windows contains an interface to the low-level operating system diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index d3b59ae69..53ee74e08 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -401,6 +401,11 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys LoadResource(module Handle, resInfo Handle) (resData Handle, err error) = kernel32.LoadResource //sys LockResource(resData Handle) (addr uintptr, err error) = kernel32.LockResource +// Version APIs +//sys GetFileVersionInfoSize(filename string, zeroHandle *Handle) (bufSize uint32, err error) = version.GetFileVersionInfoSizeW +//sys GetFileVersionInfo(filename string, handle uint32, bufSize uint32, buffer unsafe.Pointer) (err error) = version.GetFileVersionInfoW +//sys VerQueryValue(block unsafe.Pointer, subBlock string, pointerToBufferPointer unsafe.Pointer, bufSize *uint32) (err error) = version.VerQueryValueW + // Process Status API (PSAPI) //sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses //sys EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) = psapi.EnumProcessModules @@ -418,11 +423,16 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys RtlInitString(destinationString *NTString, sourceString *byte) = ntdll.RtlInitString //sys NtCreateFile(handle *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, allocationSize *int64, attributes uint32, share uint32, disposition uint32, options uint32, eabuffer uintptr, ealength uint32) (ntstatus error) = ntdll.NtCreateFile //sys NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (ntstatus error) = ntdll.NtCreateNamedPipeFile +//sys NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32, class uint32) (ntstatus error) = ntdll.NtSetInformationFile //sys RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToNtPathName_U_WithStatus //sys RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToRelativeNtPathName_U_WithStatus //sys RtlDefaultNpAcl(acl **ACL) (ntstatus error) = ntdll.RtlDefaultNpAcl //sys NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32, retLen *uint32) (ntstatus error) = ntdll.NtQueryInformationProcess //sys NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32) (ntstatus error) = ntdll.NtSetInformationProcess +//sys NtQuerySystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32, retLen *uint32) (ntstatus error) = ntdll.NtQuerySystemInformation +//sys NtSetSystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32) (ntstatus error) = ntdll.NtSetSystemInformation +//sys RtlAddFunctionTable(functionTable *RUNTIME_FUNCTION, entryCount uint32, baseAddress uintptr) (ret bool) = ntdll.RtlAddFunctionTable +//sys RtlDeleteFunctionTable(functionTable *RUNTIME_FUNCTION) (ret bool) = ntdll.RtlDeleteFunctionTable // syscall interface implementation for other packages diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index 02db2ee5e..286dd1eab 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -2366,6 +2366,12 @@ type LIST_ENTRY struct { Blink *LIST_ENTRY } +type RUNTIME_FUNCTION struct { + BeginAddress uint32 + EndAddress uint32 + UnwindData uint32 +} + type LDR_DATA_TABLE_ENTRY struct { reserved1 [2]uintptr InMemoryOrderLinks LIST_ENTRY @@ -2556,6 +2562,60 @@ const ( FILE_PIPE_SERVER_END = 0x00000001 ) +const ( + // FileInformationClass for NtSetInformationFile + FileBasicInformation = 4 + FileRenameInformation = 10 + FileDispositionInformation = 13 + FilePositionInformation = 14 + FileEndOfFileInformation = 20 + FileValidDataLengthInformation = 39 + FileShortNameInformation = 40 + FileIoPriorityHintInformation = 43 + FileReplaceCompletionInformation = 61 + FileDispositionInformationEx = 64 + FileCaseSensitiveInformation = 71 + FileLinkInformation = 72 + FileCaseSensitiveInformationForceAccessCheck = 75 + FileKnownFolderInformation = 76 + + // Flags for FILE_RENAME_INFORMATION + FILE_RENAME_REPLACE_IF_EXISTS = 0x00000001 + FILE_RENAME_POSIX_SEMANTICS = 0x00000002 + FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE = 0x00000004 + FILE_RENAME_SUPPRESS_STORAGE_RESERVE_INHERITANCE = 0x00000008 + FILE_RENAME_NO_INCREASE_AVAILABLE_SPACE = 0x00000010 + FILE_RENAME_NO_DECREASE_AVAILABLE_SPACE = 0x00000020 + FILE_RENAME_PRESERVE_AVAILABLE_SPACE = 0x00000030 + FILE_RENAME_IGNORE_READONLY_ATTRIBUTE = 0x00000040 + FILE_RENAME_FORCE_RESIZE_TARGET_SR = 0x00000080 + FILE_RENAME_FORCE_RESIZE_SOURCE_SR = 0x00000100 + FILE_RENAME_FORCE_RESIZE_SR = 0x00000180 + + // Flags for FILE_DISPOSITION_INFORMATION_EX + FILE_DISPOSITION_DO_NOT_DELETE = 0x00000000 + FILE_DISPOSITION_DELETE = 0x00000001 + FILE_DISPOSITION_POSIX_SEMANTICS = 0x00000002 + FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK = 0x00000004 + FILE_DISPOSITION_ON_CLOSE = 0x00000008 + FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE = 0x00000010 + + // Flags for FILE_CASE_SENSITIVE_INFORMATION + FILE_CS_FLAG_CASE_SENSITIVE_DIR = 0x00000001 + + // Flags for FILE_LINK_INFORMATION + FILE_LINK_REPLACE_IF_EXISTS = 0x00000001 + FILE_LINK_POSIX_SEMANTICS = 0x00000002 + FILE_LINK_SUPPRESS_STORAGE_RESERVE_INHERITANCE = 0x00000008 + FILE_LINK_NO_INCREASE_AVAILABLE_SPACE = 0x00000010 + FILE_LINK_NO_DECREASE_AVAILABLE_SPACE = 0x00000020 + FILE_LINK_PRESERVE_AVAILABLE_SPACE = 0x00000030 + FILE_LINK_IGNORE_READONLY_ATTRIBUTE = 0x00000040 + FILE_LINK_FORCE_RESIZE_TARGET_SR = 0x00000080 + FILE_LINK_FORCE_RESIZE_SOURCE_SR = 0x00000100 + FILE_LINK_FORCE_RESIZE_SR = 0x00000180 +) + // ProcessInformationClasses for NtQueryInformationProcess and NtSetInformationProcess. const ( ProcessBasicInformation = iota @@ -2672,6 +2732,203 @@ type PROCESS_BASIC_INFORMATION struct { InheritedFromUniqueProcessId uintptr } +// SystemInformationClasses for NtQuerySystemInformation and NtSetSystemInformation +const ( + SystemBasicInformation = iota + SystemProcessorInformation + SystemPerformanceInformation + SystemTimeOfDayInformation + SystemPathInformation + SystemProcessInformation + SystemCallCountInformation + SystemDeviceInformation + SystemProcessorPerformanceInformation + SystemFlagsInformation + SystemCallTimeInformation + SystemModuleInformation + SystemLocksInformation + SystemStackTraceInformation + SystemPagedPoolInformation + SystemNonPagedPoolInformation + SystemHandleInformation + SystemObjectInformation + SystemPageFileInformation + SystemVdmInstemulInformation + SystemVdmBopInformation + SystemFileCacheInformation + SystemPoolTagInformation + SystemInterruptInformation + SystemDpcBehaviorInformation + SystemFullMemoryInformation + SystemLoadGdiDriverInformation + SystemUnloadGdiDriverInformation + SystemTimeAdjustmentInformation + SystemSummaryMemoryInformation + SystemMirrorMemoryInformation + SystemPerformanceTraceInformation + systemObsolete0 + SystemExceptionInformation + SystemCrashDumpStateInformation + SystemKernelDebuggerInformation + SystemContextSwitchInformation + SystemRegistryQuotaInformation + SystemExtendServiceTableInformation + SystemPrioritySeperation + SystemVerifierAddDriverInformation + SystemVerifierRemoveDriverInformation + SystemProcessorIdleInformation + SystemLegacyDriverInformation + SystemCurrentTimeZoneInformation + SystemLookasideInformation + SystemTimeSlipNotification + SystemSessionCreate + SystemSessionDetach + SystemSessionInformation + SystemRangeStartInformation + SystemVerifierInformation + SystemVerifierThunkExtend + SystemSessionProcessInformation + SystemLoadGdiDriverInSystemSpace + SystemNumaProcessorMap + SystemPrefetcherInformation + SystemExtendedProcessInformation + SystemRecommendedSharedDataAlignment + SystemComPlusPackage + SystemNumaAvailableMemory + SystemProcessorPowerInformation + SystemEmulationBasicInformation + SystemEmulationProcessorInformation + SystemExtendedHandleInformation + SystemLostDelayedWriteInformation + SystemBigPoolInformation + SystemSessionPoolTagInformation + SystemSessionMappedViewInformation + SystemHotpatchInformation + SystemObjectSecurityMode + SystemWatchdogTimerHandler + SystemWatchdogTimerInformation + SystemLogicalProcessorInformation + SystemWow64SharedInformationObsolete + SystemRegisterFirmwareTableInformationHandler + SystemFirmwareTableInformation + SystemModuleInformationEx + SystemVerifierTriageInformation + SystemSuperfetchInformation + SystemMemoryListInformation + SystemFileCacheInformationEx + SystemThreadPriorityClientIdInformation + SystemProcessorIdleCycleTimeInformation + SystemVerifierCancellationInformation + SystemProcessorPowerInformationEx + SystemRefTraceInformation + SystemSpecialPoolInformation + SystemProcessIdInformation + SystemErrorPortInformation + SystemBootEnvironmentInformation + SystemHypervisorInformation + SystemVerifierInformationEx + SystemTimeZoneInformation + SystemImageFileExecutionOptionsInformation + SystemCoverageInformation + SystemPrefetchPatchInformation + SystemVerifierFaultsInformation + SystemSystemPartitionInformation + SystemSystemDiskInformation + SystemProcessorPerformanceDistribution + SystemNumaProximityNodeInformation + SystemDynamicTimeZoneInformation + SystemCodeIntegrityInformation + SystemProcessorMicrocodeUpdateInformation + SystemProcessorBrandString + SystemVirtualAddressInformation + SystemLogicalProcessorAndGroupInformation + SystemProcessorCycleTimeInformation + SystemStoreInformation + SystemRegistryAppendString + SystemAitSamplingValue + SystemVhdBootInformation + SystemCpuQuotaInformation + SystemNativeBasicInformation + systemSpare1 + SystemLowPriorityIoInformation + SystemTpmBootEntropyInformation + SystemVerifierCountersInformation + SystemPagedPoolInformationEx + SystemSystemPtesInformationEx + SystemNodeDistanceInformation + SystemAcpiAuditInformation + SystemBasicPerformanceInformation + SystemQueryPerformanceCounterInformation + SystemSessionBigPoolInformation + SystemBootGraphicsInformation + SystemScrubPhysicalMemoryInformation + SystemBadPageInformation + SystemProcessorProfileControlArea + SystemCombinePhysicalMemoryInformation + SystemEntropyInterruptTimingCallback + SystemConsoleInformation + SystemPlatformBinaryInformation + SystemThrottleNotificationInformation + SystemHypervisorProcessorCountInformation + SystemDeviceDataInformation + SystemDeviceDataEnumerationInformation + SystemMemoryTopologyInformation + SystemMemoryChannelInformation + SystemBootLogoInformation + SystemProcessorPerformanceInformationEx + systemSpare0 + SystemSecureBootPolicyInformation + SystemPageFileInformationEx + SystemSecureBootInformation + SystemEntropyInterruptTimingRawInformation + SystemPortableWorkspaceEfiLauncherInformation + SystemFullProcessInformation + SystemKernelDebuggerInformationEx + SystemBootMetadataInformation + SystemSoftRebootInformation + SystemElamCertificateInformation + SystemOfflineDumpConfigInformation + SystemProcessorFeaturesInformation + SystemRegistryReconciliationInformation + SystemEdidInformation + SystemManufacturingInformation + SystemEnergyEstimationConfigInformation + SystemHypervisorDetailInformation + SystemProcessorCycleStatsInformation + SystemVmGenerationCountInformation + SystemTrustedPlatformModuleInformation + SystemKernelDebuggerFlags + SystemCodeIntegrityPolicyInformation + SystemIsolatedUserModeInformation + SystemHardwareSecurityTestInterfaceResultsInformation + SystemSingleModuleInformation + SystemAllowedCpuSetsInformation + SystemDmaProtectionInformation + SystemInterruptCpuSetsInformation + SystemSecureBootPolicyFullInformation + SystemCodeIntegrityPolicyFullInformation + SystemAffinitizedInterruptProcessorInformation + SystemRootSiloInformation +) + +type RTL_PROCESS_MODULE_INFORMATION struct { + Section Handle + MappedBase uintptr + ImageBase uintptr + ImageSize uint32 + Flags uint32 + LoadOrderIndex uint16 + InitOrderIndex uint16 + LoadCount uint16 + OffsetToFileName uint16 + FullPathName [256]byte +} + +type RTL_PROCESS_MODULES struct { + NumberOfModules uint32 + Modules [1]RTL_PROCESS_MODULE_INFORMATION +} + // Constants for LocalAlloc flags. const ( LMEM_FIXED = 0x0 @@ -2766,6 +3023,22 @@ var ( RT_MANIFEST ResourceID = 24 ) +type VS_FIXEDFILEINFO struct { + Signature uint32 + StrucVersion uint32 + FileVersionMS uint32 + FileVersionLS uint32 + ProductVersionMS uint32 + ProductVersionLS uint32 + FileFlagsMask uint32 + FileFlags uint32 + FileOS uint32 + FileType uint32 + FileSubtype uint32 + FileDateMS uint32 + FileDateLS uint32 +} + type COAUTHIDENTITY struct { User *uint16 UserLength uint32 diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 4ea788e4c..ef3cfcfb2 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -51,6 +51,7 @@ var ( modshell32 = NewLazySystemDLL("shell32.dll") moduser32 = NewLazySystemDLL("user32.dll") moduserenv = NewLazySystemDLL("userenv.dll") + modversion = NewLazySystemDLL("version.dll") modwintrust = NewLazySystemDLL("wintrust.dll") modws2_32 = NewLazySystemDLL("ws2_32.dll") modwtsapi32 = NewLazySystemDLL("wtsapi32.dll") @@ -124,6 +125,7 @@ var ( procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW") procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW") procRegisterEventSourceW = modadvapi32.NewProc("RegisterEventSourceW") + procRegisterServiceCtrlHandlerExW = modadvapi32.NewProc("RegisterServiceCtrlHandlerExW") procReportEventW = modadvapi32.NewProc("ReportEventW") procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procSetEntriesInAclW = modadvapi32.NewProc("SetEntriesInAclW") @@ -364,9 +366,14 @@ var ( procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") procNtCreateFile = modntdll.NewProc("NtCreateFile") procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") + procNtSetInformationFile = modntdll.NewProc("NtSetInformationFile") procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess") + procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation") procNtSetInformationProcess = modntdll.NewProc("NtSetInformationProcess") + procNtSetSystemInformation = modntdll.NewProc("NtSetSystemInformation") + procRtlAddFunctionTable = modntdll.NewProc("RtlAddFunctionTable") procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") + procRtlDeleteFunctionTable = modntdll.NewProc("RtlDeleteFunctionTable") procRtlDosPathNameToNtPathName_U_WithStatus = modntdll.NewProc("RtlDosPathNameToNtPathName_U_WithStatus") procRtlDosPathNameToRelativeNtPathName_U_WithStatus = modntdll.NewProc("RtlDosPathNameToRelativeNtPathName_U_WithStatus") procRtlGetCurrentPeb = modntdll.NewProc("RtlGetCurrentPeb") @@ -402,6 +409,9 @@ var ( procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") + procGetFileVersionInfoSizeW = modversion.NewProc("GetFileVersionInfoSizeW") + procGetFileVersionInfoW = modversion.NewProc("GetFileVersionInfoW") + procVerQueryValueW = modversion.NewProc("VerQueryValueW") procWinVerifyTrustEx = modwintrust.NewProc("WinVerifyTrustEx") procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") @@ -1055,6 +1065,15 @@ func RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Hand return } +func RegisterServiceCtrlHandlerEx(serviceName *uint16, handlerProc uintptr, context uintptr) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procRegisterServiceCtrlHandlerExW.Addr(), 3, uintptr(unsafe.Pointer(serviceName)), uintptr(handlerProc), uintptr(context)) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + func ReportEvent(log Handle, etype uint16, category uint16, eventId uint32, usrSId uintptr, numStrings uint16, dataSize uint32, strings **uint16, rawData *byte) (err error) { r1, _, e1 := syscall.Syscall9(procReportEventW.Addr(), 9, uintptr(log), uintptr(etype), uintptr(category), uintptr(eventId), uintptr(usrSId), uintptr(numStrings), uintptr(dataSize), uintptr(unsafe.Pointer(strings)), uintptr(unsafe.Pointer(rawData))) if r1 == 0 { @@ -3152,6 +3171,14 @@ func NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, i return } +func NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32, class uint32) (ntstatus error) { + r0, _, _ := syscall.Syscall6(procNtSetInformationFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen), uintptr(class), 0) + if r0 != 0 { + ntstatus = NTStatus(r0) + } + return +} + func NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32, retLen *uint32) (ntstatus error) { r0, _, _ := syscall.Syscall6(procNtQueryInformationProcess.Addr(), 5, uintptr(proc), uintptr(procInfoClass), uintptr(procInfo), uintptr(procInfoLen), uintptr(unsafe.Pointer(retLen)), 0) if r0 != 0 { @@ -3160,6 +3187,14 @@ func NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe return } +func NtQuerySystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32, retLen *uint32) (ntstatus error) { + r0, _, _ := syscall.Syscall6(procNtQuerySystemInformation.Addr(), 4, uintptr(sysInfoClass), uintptr(sysInfo), uintptr(sysInfoLen), uintptr(unsafe.Pointer(retLen)), 0, 0) + if r0 != 0 { + ntstatus = NTStatus(r0) + } + return +} + func NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32) (ntstatus error) { r0, _, _ := syscall.Syscall6(procNtSetInformationProcess.Addr(), 4, uintptr(proc), uintptr(procInfoClass), uintptr(procInfo), uintptr(procInfoLen), 0, 0) if r0 != 0 { @@ -3168,6 +3203,20 @@ func NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.P return } +func NtSetSystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32) (ntstatus error) { + r0, _, _ := syscall.Syscall(procNtSetSystemInformation.Addr(), 3, uintptr(sysInfoClass), uintptr(sysInfo), uintptr(sysInfoLen)) + if r0 != 0 { + ntstatus = NTStatus(r0) + } + return +} + +func RtlAddFunctionTable(functionTable *RUNTIME_FUNCTION, entryCount uint32, baseAddress uintptr) (ret bool) { + r0, _, _ := syscall.Syscall(procRtlAddFunctionTable.Addr(), 3, uintptr(unsafe.Pointer(functionTable)), uintptr(entryCount), uintptr(baseAddress)) + ret = r0 != 0 + return +} + func RtlDefaultNpAcl(acl **ACL) (ntstatus error) { r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(acl)), 0, 0) if r0 != 0 { @@ -3176,6 +3225,12 @@ func RtlDefaultNpAcl(acl **ACL) (ntstatus error) { return } +func RtlDeleteFunctionTable(functionTable *RUNTIME_FUNCTION) (ret bool) { + r0, _, _ := syscall.Syscall(procRtlDeleteFunctionTable.Addr(), 1, uintptr(unsafe.Pointer(functionTable)), 0, 0) + ret = r0 != 0 + return +} + func RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) { r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U_WithStatus.Addr(), 4, uintptr(unsafe.Pointer(dosName)), uintptr(unsafe.Pointer(ntName)), uintptr(unsafe.Pointer(ntFileNamePart)), uintptr(unsafe.Pointer(relativeName)), 0, 0) if r0 != 0 { @@ -3449,6 +3504,58 @@ func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) { return } +func GetFileVersionInfoSize(filename string, zeroHandle *Handle) (bufSize uint32, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(filename) + if err != nil { + return + } + return _GetFileVersionInfoSize(_p0, zeroHandle) +} + +func _GetFileVersionInfoSize(filename *uint16, zeroHandle *Handle) (bufSize uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetFileVersionInfoSizeW.Addr(), 2, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(zeroHandle)), 0) + bufSize = uint32(r0) + if bufSize == 0 { + err = errnoErr(e1) + } + return +} + +func GetFileVersionInfo(filename string, handle uint32, bufSize uint32, buffer unsafe.Pointer) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(filename) + if err != nil { + return + } + return _GetFileVersionInfo(_p0, handle, bufSize, buffer) +} + +func _GetFileVersionInfo(filename *uint16, handle uint32, bufSize uint32, buffer unsafe.Pointer) (err error) { + r1, _, e1 := syscall.Syscall6(procGetFileVersionInfoW.Addr(), 4, uintptr(unsafe.Pointer(filename)), uintptr(handle), uintptr(bufSize), uintptr(buffer), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VerQueryValue(block unsafe.Pointer, subBlock string, pointerToBufferPointer unsafe.Pointer, bufSize *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(subBlock) + if err != nil { + return + } + return _VerQueryValue(block, _p0, pointerToBufferPointer, bufSize) +} + +func _VerQueryValue(block unsafe.Pointer, subBlock *uint16, pointerToBufferPointer unsafe.Pointer, bufSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procVerQueryValueW.Addr(), 4, uintptr(block), uintptr(unsafe.Pointer(subBlock)), uintptr(pointerToBufferPointer), uintptr(unsafe.Pointer(bufSize)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func WinVerifyTrustEx(hwnd HWND, actionId *GUID, data *WinTrustData) (ret error) { r0, _, _ := syscall.Syscall(procWinVerifyTrustEx.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(actionId)), uintptr(unsafe.Pointer(data))) if r0 != 0 { diff --git a/vendor/modules.txt b/vendor/modules.txt index 65dffcfac..4d75c6f84 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -164,7 +164,7 @@ github.com/jesseduffield/go-git/v5/utils/merkletrie/filesystem github.com/jesseduffield/go-git/v5/utils/merkletrie/index github.com/jesseduffield/go-git/v5/utils/merkletrie/internal/frame github.com/jesseduffield/go-git/v5/utils/merkletrie/noder -# github.com/jesseduffield/gocui v0.3.1-0.20211017220056-b2fc03c74a6f +# github.com/jesseduffield/gocui v0.3.1-0.20211024041248-681a61c53ed0 ## explicit github.com/jesseduffield/gocui # github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e @@ -258,7 +258,7 @@ golang.org/x/crypto/ssh/knownhosts golang.org/x/net/context golang.org/x/net/internal/socks golang.org/x/net/proxy -# golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 +# golang.org/x/sys v0.0.0-20211023085530-d6a326fbbf70 ## explicit golang.org/x/sys/cpu golang.org/x/sys/internal/unsafeheader