Compare commits
7 Commits
create-pul
...
integratio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b146c05578 | ||
|
|
6c7f893f7a | ||
|
|
8b15f22379 | ||
|
|
9c7db3a37b | ||
|
|
c961a5833b | ||
|
|
6509875009 | ||
|
|
3bf1be65b3 |
27
.github/workflows/ci.yml
vendored
27
.github/workflows/ci.yml
vendored
@@ -43,12 +43,23 @@ jobs:
|
||||
restore-keys: |
|
||||
${{runner.os}}-go-
|
||||
- name: Test code
|
||||
# we're passing -short so that we skip the integration tests, which will be run in parallel below
|
||||
# we're passing -short so that we skip the integration tests, which will be run below
|
||||
run: |
|
||||
go test ./... -short
|
||||
integration-tests:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Integration Tests"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
cache_path: ~/.cache/go-build
|
||||
- os: windows-latest
|
||||
cache_path: ~\AppData\Local\go-build
|
||||
runs-on: ${{matrix.os}}
|
||||
name: "Integration Tests - ${{matrix.os}}"
|
||||
env:
|
||||
GOFLAGS: -mod=vendor
|
||||
steps:
|
||||
@@ -59,18 +70,20 @@ jobs:
|
||||
with:
|
||||
go-version: 1.18.x
|
||||
- name: Cache build
|
||||
uses: actions/cache@v1
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
${{matrix.cache_path}}
|
||||
~/go/pkg/mod
|
||||
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-test
|
||||
restore-keys: |
|
||||
${{runner.os}}-go-
|
||||
- name: Test code
|
||||
# LONG_WAIT_BEFORE_FAIL means that for a given test assertion, we'll wait longer before failing
|
||||
env:
|
||||
# LONG_WAIT_BEFORE_FAIL means that for a given test assertion, we'll wait longer before failing
|
||||
LONG_WAIT_BEFORE_FAIL: true
|
||||
run: |
|
||||
LONG_WAIT_BEFORE_FAIL=true go test pkg/integration/clients/*.go
|
||||
go test ./pkg/integration/clients
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
|
||||
6
.vscode/tasks.json
vendored
6
.vscode/tasks.json
vendored
@@ -24,7 +24,7 @@
|
||||
{
|
||||
"label": "Run current file integration test",
|
||||
"type": "shell",
|
||||
"command": "go generate pkg/integration/tests/tests.go && go run cmd/integration_test/main.go cli ${relativeFile}",
|
||||
"command": "go run cmd/integration_test/main.go cli ${relativeFile}",
|
||||
"problemMatcher": [],
|
||||
"group": {
|
||||
"kind": "test",
|
||||
@@ -37,7 +37,7 @@
|
||||
{
|
||||
"label": "Run current file integration test (slow)",
|
||||
"type": "shell",
|
||||
"command": "go generate pkg/integration/tests/tests.go && go run cmd/integration_test/main.go cli --slow ${relativeFile}",
|
||||
"command": "go run cmd/integration_test/main.go cli --slow ${relativeFile}",
|
||||
"problemMatcher": [],
|
||||
"group": {
|
||||
"kind": "test",
|
||||
@@ -49,7 +49,7 @@
|
||||
{
|
||||
"label": "Run current file integration test (sandbox)",
|
||||
"type": "shell",
|
||||
"command": "go generate pkg/integration/tests/tests.go && go run cmd/integration_test/main.go cli --sandbox ${relativeFile}",
|
||||
"command": "go run cmd/integration_test/main.go cli --sandbox ${relativeFile}",
|
||||
"problemMatcher": [],
|
||||
"group": {
|
||||
"kind": "test",
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/clients"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
var usage = `
|
||||
@@ -49,6 +51,11 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// allowing full test paths to be passed for convenience
|
||||
testNames = lo.Map(testNames, func(name string, _ int) string {
|
||||
return components.TestNameFromFilePath(name)
|
||||
})
|
||||
|
||||
clients.RunCLI(testNames, slow, sandbox)
|
||||
case "tui":
|
||||
clients.RunTUI()
|
||||
|
||||
2
go.mod
2
go.mod
@@ -73,3 +73,5 @@ require (
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
)
|
||||
|
||||
replace github.com/creack/pty => github.com/photostorm/pty v1.1.19-0.20230324012736-6794a5ba0ba0
|
||||
|
||||
8
go.sum
8
go.sum
@@ -6,8 +6,6 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/atotto/clipboard v0.1.2 h1:YZCtFu5Ie8qX2VmVTBnrqLSiU9XOWwqNRmdT3gIQzbY=
|
||||
github.com/atotto/clipboard v0.1.2/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/aybabtme/humanlog v0.4.1 h1:D8d9um55rrthJsP8IGSHBcti9lTb/XknmDAX6Zy8tek=
|
||||
@@ -17,9 +15,6 @@ github.com/cli/safeexec v1.0.0 h1:0VngyaIyqACHdcMNWfo6+KdUYnqEr2Sg+bSP1pdF+dI=
|
||||
github.com/cli/safeexec v1.0.0/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q=
|
||||
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:tuijfIjZyjZaHq9xDUh0tNitwXshJpbLkqMOJv4H3do=
|
||||
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:po7NpZ/QiTKzBKyrsEAxwnTamCoh8uDk/egRpQ7siIc=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@@ -131,6 +126,8 @@ github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
|
||||
github.com/photostorm/pty v1.1.19-0.20230324012736-6794a5ba0ba0 h1:ahg2J7KgBYMH1KJNvde12jjJZGXwGq0AdRPztBgX2Rc=
|
||||
github.com/photostorm/pty v1.1.19-0.20230324012736-6794a5ba0ba0/go.mod h1:KO+FcPtyLAiRC0hJwreJVvfwc7vnNz77UxBTIGHdPVk=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@@ -207,6 +204,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220721230656-c6bc011c0c49/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
|
||||
@@ -4,48 +4,20 @@
|
||||
package oscommands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os/exec"
|
||||
|
||||
"github.com/sasha-s/go-deadlock"
|
||||
"github.com/creack/pty"
|
||||
)
|
||||
|
||||
type Buffer struct {
|
||||
b bytes.Buffer
|
||||
m deadlock.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)
|
||||
}
|
||||
|
||||
// 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 (self *cmdObjRunner) getCmdHandler(cmd *exec.Cmd) (*cmdHandler, error) {
|
||||
stdoutReader, stdoutWriter := io.Pipe()
|
||||
cmd.Stdout = stdoutWriter
|
||||
|
||||
buf := &Buffer{}
|
||||
cmd.Stdin = buf
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
ptmx, err := pty.Start(cmd)
|
||||
if 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 },
|
||||
stdoutPipe: ptmx,
|
||||
stdinPipe: ptmx,
|
||||
close: ptmx.Close,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/creack/pty"
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazycore/pkg/boxlayout"
|
||||
appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
|
||||
@@ -75,7 +76,7 @@ type Gui struct {
|
||||
// holds a mapping of view names to ptmx's. This is for rendering command outputs
|
||||
// from within a pty. The point of keeping track of them is so that if we re-size
|
||||
// the window, we can tell the pty it needs to resize accordingly.
|
||||
viewPtmxMap map[string]*os.File
|
||||
viewPtmxMap map[string]pty.Pty
|
||||
stopChan chan struct{}
|
||||
|
||||
// when lazygit is opened outside a git directory we want to open to the most
|
||||
@@ -436,7 +437,7 @@ func NewGui(
|
||||
Updater: updater,
|
||||
statusManager: status.NewStatusManager(),
|
||||
viewBufferManagerMap: map[string]*tasks.ViewBufferManager{},
|
||||
viewPtmxMap: map[string]*os.File{},
|
||||
viewPtmxMap: map[string]pty.Pty{},
|
||||
showRecentRepos: showRecentRepos,
|
||||
RepoPathStack: &utils.StringStack{},
|
||||
RepoStateMap: map[Repo]*GuiRepoState{},
|
||||
@@ -616,6 +617,7 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error {
|
||||
|
||||
gui.c.Log.Info("starting main loop")
|
||||
|
||||
defer gui.handlePanicInTest(startArgs.IntegrationTest)
|
||||
gui.handleTestMode(startArgs.IntegrationTest)
|
||||
|
||||
return gui.g.MainLoop()
|
||||
|
||||
@@ -70,6 +70,7 @@ func (self *GuiDriver) Fail(message string) {
|
||||
self.gui.g.Close()
|
||||
// need to give the gui time to close
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
self.Log("test failed")
|
||||
panic(fullMessage)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ package gui
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
@@ -57,7 +56,7 @@ func (gui *Gui) newPtyTask(view *gocui.View, cmd *exec.Cmd, prefix string) error
|
||||
|
||||
manager := gui.getManager(view)
|
||||
|
||||
var ptmx *os.File
|
||||
var ptmx pty.Pty
|
||||
start := func() (*exec.Cmd, io.Reader) {
|
||||
var err error
|
||||
ptmx, err = pty.StartWithSize(cmd, gui.desiredPtySize())
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package gui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/result"
|
||||
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
@@ -16,29 +19,60 @@ type IntegrationTest interface {
|
||||
}
|
||||
|
||||
func (gui *Gui) handleTestMode(test integrationTypes.IntegrationTest) {
|
||||
if os.Getenv(components.SANDBOX_ENV_VAR) == "true" {
|
||||
if os.Getenv(components.SANDBOX_ENV_VAR) == "true" || test == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if test != nil {
|
||||
go func() {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
go func() {
|
||||
defer gui.handlePanicInTest(test)
|
||||
|
||||
test.Run(&GuiDriver{gui: gui})
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
|
||||
gui.g.Update(func(*gocui.Gui) error {
|
||||
return gocui.ErrQuit
|
||||
})
|
||||
guiDriver := &GuiDriver{gui: gui}
|
||||
test.Run(guiDriver)
|
||||
|
||||
time.Sleep(time.Second * 1)
|
||||
// if we're here then the test must have passed: it panics upon failure
|
||||
gui.Log.Warnf("test %s logging success", test.Name())
|
||||
if err := result.LogSuccess(); err != nil {
|
||||
gui.Log.Warnf("test %s failed to log success!", test.Name())
|
||||
panic(err)
|
||||
}
|
||||
|
||||
log.Fatal("gocui should have already exited")
|
||||
}()
|
||||
|
||||
go utils.Safe(func() {
|
||||
time.Sleep(time.Second * 40)
|
||||
log.Fatal("40 seconds is up, lazygit recording took too long to complete")
|
||||
gui.g.Update(func(*gocui.Gui) error {
|
||||
return gocui.ErrQuit
|
||||
})
|
||||
|
||||
time.Sleep(time.Second * 1)
|
||||
|
||||
log.Fatal("gocui should have already exited")
|
||||
}()
|
||||
|
||||
go utils.Safe(func() {
|
||||
defer gui.handlePanicInTest(test)
|
||||
|
||||
time.Sleep(time.Second * 40)
|
||||
panic("40 seconds is up, lazygit recording took too long to complete")
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) handlePanicInTest(test integrationTypes.IntegrationTest) {
|
||||
if test == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r := recover(); r != nil {
|
||||
buf := make([]byte, 4096*4) // arbitrarily large buffer size
|
||||
stackSize := runtime.Stack(buf, false)
|
||||
stackTrace := string(buf[:stackSize])
|
||||
|
||||
gui.Log.Warnf("test %s panicked!", test.Name())
|
||||
|
||||
if err := result.LogFailure(fmt.Sprintf("%v\n%s", r, stackTrace)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Re-panic
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,9 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/generics/slices"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests"
|
||||
"github.com/samber/lo"
|
||||
@@ -30,6 +28,11 @@ func RunCLI(testNames []string, slow bool, sandbox bool) {
|
||||
keyPressDelay = SLOW_KEY_PRESS_DELAY
|
||||
}
|
||||
|
||||
// replace backslashes with forward slashes for windows compatibility
|
||||
testNames = lo.Map(testNames, func(name string, _ int) string {
|
||||
return strings.ReplaceAll(name, "\\", "/")
|
||||
})
|
||||
|
||||
err := components.RunTests(
|
||||
getTestsToRun(testNames),
|
||||
log.Printf,
|
||||
@@ -58,14 +61,6 @@ func getTestsToRun(testNames []string) []*components.IntegrationTest {
|
||||
return allIntegrationTests
|
||||
}
|
||||
|
||||
testNames = slices.Map(testNames, func(name string) string {
|
||||
// allowing full test paths to be passed for convenience
|
||||
return strings.TrimSuffix(
|
||||
regexp.MustCompile(`.*pkg/integration/tests/`).ReplaceAllString(name, ""),
|
||||
".go",
|
||||
)
|
||||
})
|
||||
|
||||
if lo.SomeBy(testNames, func(name string) bool {
|
||||
return strings.HasSuffix(name, "/shared")
|
||||
}) {
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package clients
|
||||
|
||||
// This file allows you to use `go test` to run integration tests.
|
||||
@@ -9,14 +6,15 @@ package clients
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/creack/pty"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/result"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -30,8 +28,10 @@ func TestIntegration(t *testing.T) {
|
||||
parallelIndex := tryConvert(os.Getenv("PARALLEL_INDEX"), 0)
|
||||
testNumber := 0
|
||||
|
||||
tests := tests.GetTests()
|
||||
|
||||
err := components.RunTests(
|
||||
tests.GetTests(),
|
||||
tests,
|
||||
t.Logf,
|
||||
runCmdHeadless,
|
||||
func(test *components.IntegrationTest, f func() error) {
|
||||
@@ -40,6 +40,10 @@ func TestIntegration(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
// if test.Name() != "commit/commit" {
|
||||
// return
|
||||
// }
|
||||
|
||||
t.Run(test.Name(), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := f()
|
||||
@@ -63,6 +67,9 @@ func runCmdHeadless(cmd *exec.Cmd) error {
|
||||
"TERM=xterm",
|
||||
)
|
||||
|
||||
resultPath := result.GetResultPath()
|
||||
result.SetResultPathEnvVar(cmd, resultPath)
|
||||
|
||||
// not writing stderr to the pty because we want to capture a panic if
|
||||
// there is one. But some commands will not be in tty mode if stderr is
|
||||
// not a terminal. We'll need to keep an eye out for that.
|
||||
@@ -72,17 +79,23 @@ func runCmdHeadless(cmd *exec.Cmd) error {
|
||||
// these rows and columns are ignored because internally we use tcell's
|
||||
// simulation screen. However we still need the pty for the sake of
|
||||
// running other commands in a pty.
|
||||
f, err := pty.StartWithSize(cmd, &pty.Winsize{Rows: 300, Cols: 300})
|
||||
_, err := pty.StartWithSize(cmd, &pty.Winsize{Rows: 300, Cols: 300})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _ = io.Copy(ioutil.Discard, f)
|
||||
_ = cmd.Wait()
|
||||
|
||||
if cmd.Wait() != nil {
|
||||
// return an error with the stderr output
|
||||
return errors.New(stderr.String())
|
||||
time.Sleep(time.Second)
|
||||
|
||||
result, err := result.ReadResult(resultPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading integration test result: %w", err)
|
||||
}
|
||||
if !result.Success {
|
||||
return errors.New(result.Message)
|
||||
}
|
||||
|
||||
return f.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ func retryWaitTimes() []int {
|
||||
// give it more leeway compared to when we're running things locally.
|
||||
return []int{0, 1, 1, 1, 1, 1, 5, 10, 20, 40, 100, 200, 500, 1000, 2000, 4000}
|
||||
} else {
|
||||
return []int{0, 1, 1, 1, 1, 1, 5, 10, 20, 40, 100, 200}
|
||||
return []int{0, 1, 1, 1, 1, 1, 5, 10, 20, 40, 100, 200, 500, 1000, 2000, 4000}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/jesseduffield/lazycore/pkg/utils"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
@@ -122,7 +123,7 @@ func prepareTestDir(
|
||||
|
||||
err := os.Mkdir(paths.ActualRepo(), 0o777)
|
||||
if err != nil {
|
||||
return err
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return createFixture(test, paths, rootDir)
|
||||
@@ -198,7 +199,12 @@ func getLazygitCommand(test *IntegrationTest, paths Paths, rootDir string, sandb
|
||||
}
|
||||
|
||||
func tempLazygitPath() string {
|
||||
return filepath.Join("/tmp", "lazygit", "test_lazygit")
|
||||
filename := "test_lazygit"
|
||||
if runtime.GOOS == "windows" {
|
||||
filename += ".exe"
|
||||
}
|
||||
|
||||
return filepath.Join(os.TempDir(), "lazygit", filename)
|
||||
}
|
||||
|
||||
func findOrCreateDir(path string) {
|
||||
|
||||
@@ -2,6 +2,8 @@ package components
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -170,10 +172,14 @@ func testNameFromCurrentFilePath() string {
|
||||
return TestNameFromFilePath(path)
|
||||
}
|
||||
|
||||
// takes either a path or a test name and returns a test name
|
||||
// so commit/commit -> commit/commit
|
||||
// and /my/path/to/lazygit/pkg/integration/tests/commit/commit -> commit/commit
|
||||
func TestNameFromFilePath(path string) string {
|
||||
name := strings.Split(path, "integration/tests/")[1]
|
||||
|
||||
return name[:len(name)-len(".go")]
|
||||
return strings.TrimSuffix(
|
||||
regexp.MustCompile(`.*pkg/integration/tests/`).ReplaceAllString(filepath.ToSlash(path), ""),
|
||||
".go",
|
||||
)
|
||||
}
|
||||
|
||||
// this is the delay in milliseconds between keypresses
|
||||
|
||||
103
pkg/integration/result/result.go
Normal file
103
pkg/integration/result/result.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package result
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// On windows the pty package is failing to obtain stderr text when a test fails,
|
||||
// so this is our workaround: when a test fails, it writes the result to a file,
|
||||
// and then the test runner reads the file and checks the result
|
||||
|
||||
const PathEnvVar = "LAZYGIT_INTEGRATION_TEST_RESULT_PATH"
|
||||
|
||||
type IntegrationTestResult struct {
|
||||
Success bool
|
||||
Message string
|
||||
}
|
||||
|
||||
func LogFailure(message string) error {
|
||||
return writeResult(failure(message))
|
||||
}
|
||||
|
||||
func LogSuccess() error {
|
||||
return writeResult(success())
|
||||
}
|
||||
|
||||
func failure(message string) IntegrationTestResult {
|
||||
return IntegrationTestResult{Success: false, Message: message}
|
||||
}
|
||||
|
||||
func success() IntegrationTestResult {
|
||||
return IntegrationTestResult{Success: true}
|
||||
}
|
||||
|
||||
func writeResult(result IntegrationTestResult) error {
|
||||
resultPath := os.Getenv(PathEnvVar)
|
||||
if resultPath == "" {
|
||||
// path env var not set so we'll assume we don't need to write the result to a file
|
||||
return nil
|
||||
}
|
||||
|
||||
file, err := os.Create(resultPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating file: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
encoder := json.NewEncoder(file)
|
||||
err = encoder.Encode(result)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error encoding JSON: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reads the result file stored by the lazygit test, and deletes the file
|
||||
func ReadResult(resultPath string) (IntegrationTestResult, error) {
|
||||
file, err := os.Open(resultPath)
|
||||
if err != nil {
|
||||
return IntegrationTestResult{}, fmt.Errorf("Error reading file: %w", err)
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(file)
|
||||
var result IntegrationTestResult
|
||||
err = decoder.Decode(&result)
|
||||
if err != nil {
|
||||
file.Close()
|
||||
return IntegrationTestResult{}, fmt.Errorf("Error decoding JSON: %w", err)
|
||||
}
|
||||
|
||||
file.Close()
|
||||
// _ = os.Remove(resultPath)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func SetResultPathEnvVar(cmd *exec.Cmd, resultPath string) {
|
||||
cmd.Env = append(
|
||||
cmd.Env,
|
||||
fmt.Sprintf("%s=%s", PathEnvVar, resultPath),
|
||||
)
|
||||
}
|
||||
|
||||
func GetResultPath() string {
|
||||
return filepath.Join(os.TempDir(), fmt.Sprintf("lazygit_result_%s.json", generateRandomString(10)))
|
||||
}
|
||||
|
||||
func generateRandomString(length int) string {
|
||||
buffer := make([]byte, length)
|
||||
_, err := rand.Read(buffer)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Could not generate random string: %s", err))
|
||||
}
|
||||
|
||||
randomString := base64.URLEncoding.EncodeToString(buffer)
|
||||
return randomString[:length]
|
||||
}
|
||||
@@ -27,7 +27,7 @@ var Commit = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
PressPrimaryAction(). // stage file
|
||||
Lines(
|
||||
Contains("A myfile").IsSelected(),
|
||||
Contains("?? myfile2"),
|
||||
Contains("?? myfile23"),
|
||||
).
|
||||
SelectNextItem().
|
||||
PressPrimaryAction(). // stage other file
|
||||
@@ -55,7 +55,7 @@ var Commit = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
IsFocused().
|
||||
Lines(
|
||||
Contains("A myfile"),
|
||||
Contains("A myfile2"),
|
||||
Contains("A myfile3"),
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
@@ -27,7 +27,7 @@ func GetTests() []*components.IntegrationTest {
|
||||
|
||||
missingTestNames := []string{}
|
||||
|
||||
if err := filepath.Walk(filepath.Join(utils.GetLazyRootDirectory(), "pkg/integration/tests"), func(path string, info os.FileInfo, err error) error {
|
||||
if err := filepath.Walk(filepath.Join(utils.GetLazyRootDirectory(), "pkg", "integration", "tests"), func(path string, info os.FileInfo, err error) error {
|
||||
if !info.IsDir() && strings.HasSuffix(path, ".go") {
|
||||
// ignoring non-test files
|
||||
if filepath.Base(path) == "tests.go" || filepath.Base(path) == "test_list.go" || filepath.Base(path) == "test_list_generator.go" {
|
||||
|
||||
@@ -16,6 +16,9 @@ var DoublePopup = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Branches().
|
||||
Focus().
|
||||
Lines(
|
||||
Contains("master"),
|
||||
).
|
||||
// arbitrarily bringing up a popup
|
||||
PressPrimaryAction()
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
type IntegrationTest interface {
|
||||
Run(GuiDriver)
|
||||
SetupConfig(config *config.AppConfig)
|
||||
Name() string
|
||||
}
|
||||
|
||||
// this is the interface through which our integration tests interact with the lazygit gui
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
var Global *logrus.Entry
|
||||
|
||||
func init() {
|
||||
logPath := os.Getenv("LAZYGIT_LOG_PATH")
|
||||
logPath := `C:\Users\New\AppData\Roaming\jesseduffield\lazygit\development.log`
|
||||
if logPath != "" {
|
||||
Global = NewDevelopmentLogger(logPath)
|
||||
}
|
||||
@@ -35,6 +35,7 @@ func NewProductionLogger() *logrus.Entry {
|
||||
}
|
||||
|
||||
func NewDevelopmentLogger(logPath string) *logrus.Entry {
|
||||
logPath = `C:\Users\New\AppData\Roaming\jesseduffield\lazygit\development.log`
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(getLogLevel())
|
||||
|
||||
|
||||
@@ -8,20 +8,15 @@
|
||||
# this will hang if you're using git from the command line, so only enable this
|
||||
# when you are testing the credentials view in lazygit
|
||||
|
||||
exec < /dev/tty
|
||||
read -p "Username for 'github': " username
|
||||
read -p "Password for 'github': " password
|
||||
|
||||
echo -n "Username for 'github': "
|
||||
read username
|
||||
echo
|
||||
|
||||
echo -n "Password for 'github': "
|
||||
# this will print the password to the log view but real git won't do that.
|
||||
# We could use read -s but that's not POSIX compliant.
|
||||
read password
|
||||
|
||||
if [ "$username" = "username" -a "$password" = "password" ]; then
|
||||
if [[ "$username" == "username" && "$password" == "password" ]]; then
|
||||
echo "success"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
>&2 echo "incorrect username/password"
|
||||
echo "incorrect username/password" >&2
|
||||
exit 1
|
||||
|
||||
17
vendor/github.com/creack/pty/Dockerfile.golang
generated
vendored
Normal file
17
vendor/github.com/creack/pty/Dockerfile.golang
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
ARG GOVERSION=1.14
|
||||
FROM golang:${GOVERSION}
|
||||
|
||||
# Set base env.
|
||||
ARG GOOS=linux
|
||||
ARG GOARCH=amd64
|
||||
ENV GOOS=${GOOS} GOARCH=${GOARCH} CGO_ENABLED=0 GOFLAGS='-v -ldflags=-s -ldflags=-w'
|
||||
|
||||
# Pre compile the stdlib for 386/arm (32bits).
|
||||
RUN go build -a std
|
||||
|
||||
# Add the code to the image.
|
||||
WORKDIR pty
|
||||
ADD . .
|
||||
|
||||
# Build the lib.
|
||||
RUN go build
|
||||
13
vendor/github.com/creack/pty/Dockerfile.riscv
generated
vendored
13
vendor/github.com/creack/pty/Dockerfile.riscv
generated
vendored
@@ -1,3 +1,4 @@
|
||||
# NOTE: Using 1.13 as a base to build the RISCV compiler, the resulting version is based on go1.6.
|
||||
FROM golang:1.13
|
||||
|
||||
# Clone and complie a riscv compatible version of the go compiler.
|
||||
@@ -8,7 +9,15 @@ ENV PATH=/riscv-go/misc/riscv:/riscv-go/bin:$PATH
|
||||
RUN cd /riscv-go/src && GOROOT_BOOTSTRAP=$(go env GOROOT) ./make.bash
|
||||
ENV GOROOT=/riscv-go
|
||||
|
||||
# Make sure we compile.
|
||||
# Set the base env.
|
||||
ENV GOOS=linux GOARCH=riscv CGO_ENABLED=0 GOFLAGS='-v -ldflags=-s -ldflags=-w'
|
||||
|
||||
# Pre compile the stdlib.
|
||||
RUN go build -a std
|
||||
|
||||
# Add the code to the image.
|
||||
WORKDIR pty
|
||||
ADD . .
|
||||
RUN GOOS=linux GOARCH=riscv go build
|
||||
|
||||
# Build the lib.
|
||||
RUN go build
|
||||
|
||||
23
vendor/github.com/creack/pty/README.md
generated
vendored
23
vendor/github.com/creack/pty/README.md
generated
vendored
@@ -1,12 +1,18 @@
|
||||
# pty
|
||||
|
||||
Pty is a Go package for using unix pseudo-terminals.
|
||||
Pty is a Go package for using unix pseudo-terminals and windows ConPty.
|
||||
|
||||
## Install
|
||||
|
||||
go get github.com/creack/pty
|
||||
```sh
|
||||
go get github.com/creack/pty
|
||||
```
|
||||
|
||||
## Example
|
||||
## Examples
|
||||
|
||||
Note that those examples are for demonstration purpose only, to showcase how to use the library. They are not meant to be used in any kind of production environment.
|
||||
|
||||
__NOTE:__ This package requires `ConPty` support on windows platform, please make sure your windows system meet [these requirements](https://docs.microsoft.com/en-us/windows/console/createpseudoconsole#requirements)
|
||||
|
||||
### Command
|
||||
|
||||
@@ -14,10 +20,11 @@ Pty is a Go package for using unix pseudo-terminals.
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/creack/pty"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/creack/pty"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -51,7 +58,7 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/creack/pty"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
func test() error {
|
||||
@@ -77,15 +84,17 @@ func test() error {
|
||||
}
|
||||
}()
|
||||
ch <- syscall.SIGWINCH // Initial resize.
|
||||
defer func() { signal.Stop(ch); close(ch) }() // Cleanup signals when done.
|
||||
|
||||
// Set stdin in raw mode.
|
||||
oldState, err := terminal.MakeRaw(int(os.Stdin.Fd()))
|
||||
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer func() { _ = terminal.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.
|
||||
defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.
|
||||
|
||||
// Copy stdin to the pty and the pty to stdout.
|
||||
// NOTE: The goroutine will keep reading until the next keystroke before returning.
|
||||
go func() { _, _ = io.Copy(ptmx, os.Stdin) }()
|
||||
_, _ = io.Copy(os.Stdout, ptmx)
|
||||
|
||||
|
||||
18
vendor/github.com/creack/pty/asm_solaris_amd64.s
generated
vendored
Normal file
18
vendor/github.com/creack/pty/asm_solaris_amd64.s
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc
|
||||
//+build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go
|
||||
//
|
||||
|
||||
TEXT ·sysvicall6(SB),NOSPLIT,$0-88
|
||||
JMP syscall·sysvicall6(SB)
|
||||
|
||||
TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88
|
||||
JMP syscall·rawSysvicall6(SB)
|
||||
356
vendor/github.com/creack/pty/cmd_windows.go
generated
vendored
Normal file
356
vendor/github.com/creack/pty/cmd_windows.go
generated
vendored
Normal file
@@ -0,0 +1,356 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// copied from os/exec.Cmd for platform compatibility
|
||||
// we need to use startupInfoEx for pty support, but os/exec.Cmd only have
|
||||
// support for startupInfo on windows, so we have to rewrite some internal
|
||||
// logic for windows while keep its behavior compatible with other platforms.
|
||||
|
||||
// windowExecCmd represents an external command being prepared or run.
|
||||
//
|
||||
// A cmd cannot be reused after calling its Run, Output or CombinedOutput
|
||||
// methods.
|
||||
type windowExecCmd struct {
|
||||
cmd *exec.Cmd
|
||||
waitCalled bool
|
||||
conPty *WindowsPty
|
||||
attrList *windows.ProcThreadAttributeListContainer
|
||||
}
|
||||
|
||||
var errProcessNotStarted = errors.New("exec: process has not started yet")
|
||||
|
||||
func (c *windowExecCmd) close() error {
|
||||
c.attrList.Delete()
|
||||
_ = c.conPty.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *windowExecCmd) Run() error {
|
||||
err := c.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Wait()
|
||||
}
|
||||
|
||||
func (c *windowExecCmd) Wait() error {
|
||||
if c.cmd.Process == nil {
|
||||
return errProcessNotStarted
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if c.waitCalled {
|
||||
return errors.New("exec: wait was already called")
|
||||
}
|
||||
|
||||
c.waitCalled = true
|
||||
c.cmd.ProcessState, err = c.cmd.Process.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.cmd.ProcessState.Success() {
|
||||
return &exec.ExitError{ProcessState: c.cmd.ProcessState}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *windowExecCmd) StdinPipe() (io.WriteCloser, error) {
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
|
||||
func (c *windowExecCmd) StdoutPipe() (io.ReadCloser, error) {
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
|
||||
func (c *windowExecCmd) StderrPipe() (io.ReadCloser, error) {
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
|
||||
func (c *windowExecCmd) Output() ([]byte, error) {
|
||||
if c.cmd.Stdout != nil {
|
||||
return nil, errors.New("exec: Stdout already set")
|
||||
}
|
||||
|
||||
var stdout bytes.Buffer
|
||||
c.cmd.Stdout = &stdout
|
||||
|
||||
err := c.Run()
|
||||
return stdout.Bytes(), err
|
||||
}
|
||||
|
||||
func (c *windowExecCmd) CombinedOutput() ([]byte, error) {
|
||||
if c.cmd.Stdout != nil {
|
||||
return nil, errors.New("exec: Stdout already set")
|
||||
}
|
||||
if c.cmd.Stderr != nil {
|
||||
return nil, errors.New("exec: Stderr already set")
|
||||
}
|
||||
var b bytes.Buffer
|
||||
c.cmd.Stdout = &b
|
||||
c.cmd.Stderr = &b
|
||||
err := c.Run()
|
||||
return b.Bytes(), err
|
||||
}
|
||||
|
||||
func (c *windowExecCmd) argv() []string {
|
||||
if len(c.cmd.Args) > 0 {
|
||||
return c.cmd.Args
|
||||
}
|
||||
|
||||
return []string{c.cmd.Path}
|
||||
}
|
||||
|
||||
//
|
||||
// Helpers for working with Windows. These are exact copies of the same utilities found in the go stdlib.
|
||||
//
|
||||
|
||||
func lookExtensions(path, dir string) (string, error) {
|
||||
if filepath.Base(path) == path {
|
||||
path = filepath.Join(".", path)
|
||||
}
|
||||
|
||||
if dir == "" {
|
||||
return exec.LookPath(path)
|
||||
}
|
||||
|
||||
if filepath.VolumeName(path) != "" {
|
||||
return exec.LookPath(path)
|
||||
}
|
||||
|
||||
if len(path) > 1 && os.IsPathSeparator(path[0]) {
|
||||
return exec.LookPath(path)
|
||||
}
|
||||
|
||||
dirandpath := filepath.Join(dir, path)
|
||||
|
||||
// We assume that LookPath will only add file extension.
|
||||
lp, err := exec.LookPath(dirandpath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ext := strings.TrimPrefix(lp, dirandpath)
|
||||
|
||||
return path + ext, nil
|
||||
}
|
||||
|
||||
func dedupEnvCase(caseInsensitive bool, env []string) []string {
|
||||
// Construct the output in reverse order, to preserve the
|
||||
// last occurrence of each key.
|
||||
out := make([]string, 0, len(env))
|
||||
saw := make(map[string]bool, len(env))
|
||||
for n := len(env); n > 0; n-- {
|
||||
kv := env[n-1]
|
||||
|
||||
i := strings.Index(kv, "=")
|
||||
if i == 0 {
|
||||
// We observe in practice keys with a single leading "=" on Windows.
|
||||
// TODO(#49886): Should we consume only the first leading "=" as part
|
||||
// of the key, or parse through arbitrarily many of them until a non-"="?
|
||||
i = strings.Index(kv[1:], "=") + 1
|
||||
}
|
||||
if i < 0 {
|
||||
if kv != "" {
|
||||
// The entry is not of the form "key=value" (as it is required to be).
|
||||
// Leave it as-is for now.
|
||||
// TODO(#52436): should we strip or reject these bogus entries?
|
||||
out = append(out, kv)
|
||||
}
|
||||
continue
|
||||
}
|
||||
k := kv[:i]
|
||||
if caseInsensitive {
|
||||
k = strings.ToLower(k)
|
||||
}
|
||||
if saw[k] {
|
||||
continue
|
||||
}
|
||||
|
||||
saw[k] = true
|
||||
out = append(out, kv)
|
||||
}
|
||||
|
||||
// Now reverse the slice to restore the original order.
|
||||
for i := 0; i < len(out)/2; i++ {
|
||||
j := len(out) - i - 1
|
||||
out[i], out[j] = out[j], out[i]
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func addCriticalEnv(env []string) []string {
|
||||
for _, kv := range env {
|
||||
eq := strings.Index(kv, "=")
|
||||
if eq < 0 {
|
||||
continue
|
||||
}
|
||||
k := kv[:eq]
|
||||
if strings.EqualFold(k, "SYSTEMROOT") {
|
||||
// We already have it.
|
||||
return env
|
||||
}
|
||||
}
|
||||
|
||||
return append(env, "SYSTEMROOT="+os.Getenv("SYSTEMROOT"))
|
||||
}
|
||||
|
||||
func execEnvDefault(sys *syscall.SysProcAttr) (env []string, err error) {
|
||||
if sys == nil || sys.Token == 0 {
|
||||
return syscall.Environ(), nil
|
||||
}
|
||||
|
||||
var block *uint16
|
||||
err = windows.CreateEnvironmentBlock(&block, windows.Token(sys.Token), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer windows.DestroyEnvironmentBlock(block)
|
||||
blockp := uintptr(unsafe.Pointer(block))
|
||||
|
||||
for {
|
||||
|
||||
// find NUL terminator
|
||||
end := unsafe.Pointer(blockp)
|
||||
for *(*uint16)(end) != 0 {
|
||||
end = unsafe.Pointer(uintptr(end) + 2)
|
||||
}
|
||||
|
||||
n := (uintptr(end) - uintptr(unsafe.Pointer(blockp))) / 2
|
||||
if n == 0 {
|
||||
// environment block ends with empty string
|
||||
break
|
||||
}
|
||||
|
||||
entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(blockp))[:n:n]
|
||||
env = append(env, string(utf16.Decode(entry)))
|
||||
blockp += 2 * (uintptr(len(entry)) + 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createEnvBlock(envv []string) *uint16 {
|
||||
if len(envv) == 0 {
|
||||
return &utf16.Encode([]rune("\x00\x00"))[0]
|
||||
}
|
||||
length := 0
|
||||
for _, s := range envv {
|
||||
length += len(s) + 1
|
||||
}
|
||||
length += 1
|
||||
|
||||
b := make([]byte, length)
|
||||
i := 0
|
||||
for _, s := range envv {
|
||||
l := len(s)
|
||||
copy(b[i:i+l], []byte(s))
|
||||
copy(b[i+l:i+l+1], []byte{0})
|
||||
i = i + l + 1
|
||||
}
|
||||
copy(b[i:i+1], []byte{0})
|
||||
|
||||
return &utf16.Encode([]rune(string(b)))[0]
|
||||
}
|
||||
|
||||
func makeCmdLine(args []string) string {
|
||||
var s string
|
||||
for _, v := range args {
|
||||
if s != "" {
|
||||
s += " "
|
||||
}
|
||||
s += windows.EscapeArg(v)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func isSlash(c uint8) bool {
|
||||
return c == '\\' || c == '/'
|
||||
}
|
||||
|
||||
func normalizeDir(dir string) (name string, err error) {
|
||||
ndir, err := syscall.FullPath(dir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(ndir) > 2 && isSlash(ndir[0]) && isSlash(ndir[1]) {
|
||||
// dir cannot have \\server\share\path form
|
||||
return "", syscall.EINVAL
|
||||
}
|
||||
return ndir, nil
|
||||
}
|
||||
|
||||
func volToUpper(ch int) int {
|
||||
if 'a' <= ch && ch <= 'z' {
|
||||
ch += 'A' - 'a'
|
||||
}
|
||||
return ch
|
||||
}
|
||||
|
||||
func joinExeDirAndFName(dir, p string) (name string, err error) {
|
||||
if len(p) == 0 {
|
||||
return "", syscall.EINVAL
|
||||
}
|
||||
if len(p) > 2 && isSlash(p[0]) && isSlash(p[1]) {
|
||||
// \\server\share\path form
|
||||
return p, nil
|
||||
}
|
||||
if len(p) > 1 && p[1] == ':' {
|
||||
// has drive letter
|
||||
if len(p) == 2 {
|
||||
return "", syscall.EINVAL
|
||||
}
|
||||
if isSlash(p[2]) {
|
||||
return p, nil
|
||||
} else {
|
||||
d, err := normalizeDir(dir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if volToUpper(int(p[0])) == volToUpper(int(d[0])) {
|
||||
return syscall.FullPath(d + "\\" + p[2:])
|
||||
} else {
|
||||
return syscall.FullPath(p)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no drive letter
|
||||
d, err := normalizeDir(dir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if isSlash(p[0]) {
|
||||
return windows.FullPath(d[:2] + p)
|
||||
} else {
|
||||
return windows.FullPath(d + "\\" + p)
|
||||
}
|
||||
}
|
||||
}
|
||||
36
vendor/github.com/creack/pty/doc.go
generated
vendored
36
vendor/github.com/creack/pty/doc.go
generated
vendored
@@ -3,14 +3,44 @@ package pty
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ErrUnsupported is returned if a function is not
|
||||
// available on the current platform.
|
||||
var ErrUnsupported = errors.New("unsupported")
|
||||
|
||||
// Opens a pty and its corresponding tty.
|
||||
func Open() (pty, tty *os.File, err error) {
|
||||
// Open a pty and its corresponding tty.
|
||||
func Open() (Pty, Tty, error) {
|
||||
return open()
|
||||
}
|
||||
|
||||
type FdHolder interface {
|
||||
Fd() uintptr
|
||||
}
|
||||
|
||||
// Pty for terminal control in current process
|
||||
// for unix systems, the real type is *os.File
|
||||
// for windows, the real type is a *WindowsPty for ConPTY handle
|
||||
type Pty interface {
|
||||
// FdHolder Fd intended to resize Tty of child process in current process
|
||||
FdHolder
|
||||
|
||||
Name() string
|
||||
|
||||
// WriteString is only used to identify Pty and Tty
|
||||
WriteString(s string) (n int, err error)
|
||||
io.ReadWriteCloser
|
||||
}
|
||||
|
||||
// Tty for data i/o in child process
|
||||
// for unix systems, the real type is *os.File
|
||||
// for windows, the real type is a *WindowsTty, which is a combination of two pipe file
|
||||
type Tty interface {
|
||||
// FdHolder Fd only intended for manual InheritSize from Pty
|
||||
FdHolder
|
||||
|
||||
Name() string
|
||||
|
||||
io.ReadWriteCloser
|
||||
}
|
||||
|
||||
8
vendor/github.com/creack/pty/ioctl.go
generated
vendored
8
vendor/github.com/creack/pty/ioctl.go
generated
vendored
@@ -1,9 +1,15 @@
|
||||
// +build !windows,!solaris
|
||||
//go:build !windows && !solaris && !aix
|
||||
// +build !windows,!solaris,!aix
|
||||
|
||||
package pty
|
||||
|
||||
import "syscall"
|
||||
|
||||
const (
|
||||
TIOCGWINSZ = syscall.TIOCGWINSZ
|
||||
TIOCSWINSZ = syscall.TIOCSWINSZ
|
||||
)
|
||||
|
||||
func ioctl(fd, cmd, ptr uintptr) error {
|
||||
_, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr)
|
||||
if e != 0 {
|
||||
|
||||
1
vendor/github.com/creack/pty/ioctl_bsd.go
generated
vendored
1
vendor/github.com/creack/pty/ioctl_bsd.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build darwin || dragonfly || freebsd || netbsd || openbsd
|
||||
// +build darwin dragonfly freebsd netbsd openbsd
|
||||
|
||||
package pty
|
||||
|
||||
36
vendor/github.com/creack/pty/ioctl_solaris.go
generated
vendored
36
vendor/github.com/creack/pty/ioctl_solaris.go
generated
vendored
@@ -1,30 +1,48 @@
|
||||
//go:build solaris
|
||||
// +build solaris
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//go:cgo_import_dynamic libc_ioctl ioctl "libc.so"
|
||||
//go:linkname procioctl libc_ioctl
|
||||
var procioctl uintptr
|
||||
|
||||
const (
|
||||
// see /usr/include/sys/stropts.h
|
||||
I_PUSH = uintptr((int32('S')<<8 | 002))
|
||||
I_STR = uintptr((int32('S')<<8 | 010))
|
||||
I_FIND = uintptr((int32('S')<<8 | 013))
|
||||
I_PUSH = uintptr((int32('S')<<8 | 002))
|
||||
I_STR = uintptr((int32('S')<<8 | 010))
|
||||
I_FIND = uintptr((int32('S')<<8 | 013))
|
||||
|
||||
// see /usr/include/sys/ptms.h
|
||||
ISPTM = (int32('P') << 8) | 1
|
||||
UNLKPT = (int32('P') << 8) | 2
|
||||
PTSSTTY = (int32('P') << 8) | 3
|
||||
ZONEPT = (int32('P') << 8) | 4
|
||||
OWNERPT = (int32('P') << 8) | 5
|
||||
|
||||
// see /usr/include/sys/termios.h
|
||||
TIOCSWINSZ = (uint32('T') << 8) | 103
|
||||
TIOCGWINSZ = (uint32('T') << 8) | 104
|
||||
)
|
||||
|
||||
type strioctl struct {
|
||||
ic_cmd int32
|
||||
ic_timout int32
|
||||
ic_len int32
|
||||
ic_dp unsafe.Pointer
|
||||
icCmd int32
|
||||
icTimeout int32
|
||||
icLen int32
|
||||
icDP unsafe.Pointer
|
||||
}
|
||||
|
||||
// Defined in asm_solaris_amd64.s.
|
||||
func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
func ioctl(fd, cmd, ptr uintptr) error {
|
||||
return unix.IoctlSetInt(int(fd), uint(cmd), int(ptr))
|
||||
if _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procioctl)), 3, fd, cmd, ptr, 0, 0, 0); errno != 0 {
|
||||
return errno
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
13
vendor/github.com/creack/pty/ioctl_unsupported.go
generated
vendored
Normal file
13
vendor/github.com/creack/pty/ioctl_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
//go:build aix
|
||||
// +build aix
|
||||
|
||||
package pty
|
||||
|
||||
const (
|
||||
TIOCGWINSZ = 0
|
||||
TIOCSWINSZ = 0
|
||||
)
|
||||
|
||||
func ioctl(fd, cmd, ptr uintptr) error {
|
||||
return ErrUnsupported
|
||||
}
|
||||
2
vendor/github.com/creack/pty/mktypes.bash
generated
vendored
2
vendor/github.com/creack/pty/mktypes.bash
generated
vendored
@@ -13,7 +13,7 @@ GODEFS="go tool cgo -godefs"
|
||||
$GODEFS types.go |gofmt > ztypes_$GOARCH.go
|
||||
|
||||
case $GOOS in
|
||||
freebsd|dragonfly|openbsd)
|
||||
freebsd|dragonfly|netbsd|openbsd)
|
||||
$GODEFS types_$GOOS.go |gofmt > ztypes_$GOOSARCH.go
|
||||
;;
|
||||
esac
|
||||
|
||||
5
vendor/github.com/creack/pty/pty_darwin.go
generated
vendored
5
vendor/github.com/creack/pty/pty_darwin.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
@@ -33,7 +36,7 @@ func open() (pty, tty *os.File, err error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
t, err := os.OpenFile(sname, os.O_RDWR, 0)
|
||||
t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
3
vendor/github.com/creack/pty/pty_dragonfly.go
generated
vendored
3
vendor/github.com/creack/pty/pty_dragonfly.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build dragonfly
|
||||
// +build dragonfly
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
|
||||
3
vendor/github.com/creack/pty/pty_freebsd.go
generated
vendored
3
vendor/github.com/creack/pty/pty_freebsd.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
|
||||
9
vendor/github.com/creack/pty/pty_linux.go
generated
vendored
9
vendor/github.com/creack/pty/pty_linux.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
@@ -28,7 +31,7 @@ func open() (pty, tty *os.File, err error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
|
||||
t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) //nolint:gosec // Expected Open from a variable.
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -37,7 +40,7 @@ func open() (pty, tty *os.File, err error) {
|
||||
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
var n _C_uint
|
||||
err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n)))
|
||||
err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) //nolint:gosec // Expected unsafe pointer for Syscall call.
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -47,5 +50,5 @@ func ptsname(f *os.File) (string, error) {
|
||||
func unlockpt(f *os.File) error {
|
||||
var u _C_int
|
||||
// use TIOCSPTLCK with a pointer to zero to clear the lock
|
||||
return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u)))
|
||||
return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) //nolint:gosec // Expected unsafe pointer for Syscall call.
|
||||
}
|
||||
|
||||
69
vendor/github.com/creack/pty/pty_netbsd.go
generated
vendored
Normal file
69
vendor/github.com/creack/pty/pty_netbsd.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
//go:build netbsd
|
||||
// +build netbsd
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func open() (pty, tty *os.File, err error) {
|
||||
p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// In case of error after this point, make sure we close the ptmx fd.
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = p.Close() // Best effort.
|
||||
}
|
||||
}()
|
||||
|
||||
sname, err := ptsname(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := grantpt(p); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// In NetBSD unlockpt() does nothing, so it isn't called here.
|
||||
|
||||
t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return p, t, nil
|
||||
}
|
||||
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
/*
|
||||
* from ptsname(3): The ptsname() function is equivalent to:
|
||||
* struct ptmget pm;
|
||||
* ioctl(fd, TIOCPTSNAME, &pm) == -1 ? NULL : pm.sn;
|
||||
*/
|
||||
var ptm ptmget
|
||||
if err := ioctl(f.Fd(), uintptr(ioctl_TIOCPTSNAME), uintptr(unsafe.Pointer(&ptm))); err != nil {
|
||||
return "", err
|
||||
}
|
||||
name := make([]byte, len(ptm.Sn))
|
||||
for i, c := range ptm.Sn {
|
||||
name[i] = byte(c)
|
||||
if c == 0 {
|
||||
return string(name[:i]), nil
|
||||
}
|
||||
}
|
||||
return "", errors.New("TIOCPTSNAME string not NUL-terminated")
|
||||
}
|
||||
|
||||
func grantpt(f *os.File) error {
|
||||
/*
|
||||
* from grantpt(3): Calling grantpt() is equivalent to:
|
||||
* ioctl(fd, TIOCGRANTPT, 0);
|
||||
*/
|
||||
return ioctl(f.Fd(), uintptr(ioctl_TIOCGRANTPT), 0)
|
||||
}
|
||||
18
vendor/github.com/creack/pty/pty_openbsd.go
generated
vendored
18
vendor/github.com/creack/pty/pty_openbsd.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build openbsd
|
||||
// +build openbsd
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
@@ -6,6 +9,17 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func cInt8ToString(in []int8) string {
|
||||
var s []byte
|
||||
for _, v := range in {
|
||||
if v == 0 {
|
||||
break
|
||||
}
|
||||
s = append(s, byte(v))
|
||||
}
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func open() (pty, tty *os.File, err error) {
|
||||
/*
|
||||
* from ptm(4):
|
||||
@@ -26,8 +40,8 @@ func open() (pty, tty *os.File, err error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pty = os.NewFile(uintptr(ptm.Cfd), "/dev/ptm")
|
||||
tty = os.NewFile(uintptr(ptm.Sfd), "/dev/ptm")
|
||||
pty = os.NewFile(uintptr(ptm.Cfd), cInt8ToString(ptm.Cn[:]))
|
||||
tty = os.NewFile(uintptr(ptm.Sfd), cInt8ToString(ptm.Sn[:]))
|
||||
|
||||
return pty, tty, nil
|
||||
}
|
||||
|
||||
153
vendor/github.com/creack/pty/pty_solaris.go
generated
vendored
153
vendor/github.com/creack/pty/pty_solaris.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build solaris
|
||||
// +build solaris
|
||||
|
||||
package pty
|
||||
|
||||
/* based on:
|
||||
@@ -6,122 +9,134 @@ http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/pt.c
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"golang.org/x/sys/unix"
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const NODEV = ^uint64(0)
|
||||
|
||||
func open() (pty, tty *os.File, err error) {
|
||||
masterfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|unix.O_NOCTTY, 0)
|
||||
//masterfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_CLOEXEC|unix.O_NOCTTY, 0)
|
||||
ptmxfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
p := os.NewFile(uintptr(masterfd), "/dev/ptmx")
|
||||
p := os.NewFile(uintptr(ptmxfd), "/dev/ptmx")
|
||||
// In case of error after this point, make sure we close the ptmx fd.
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = p.Close() // Best effort.
|
||||
}
|
||||
}()
|
||||
|
||||
sname, err := ptsname(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
err = grantpt(p)
|
||||
if err != nil {
|
||||
if err := grantpt(p); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
err = unlockpt(p)
|
||||
if err != nil {
|
||||
if err := unlockpt(p); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
slavefd, err := syscall.Open(sname, os.O_RDWR|unix.O_NOCTTY, 0)
|
||||
ptsfd, err := syscall.Open(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
t := os.NewFile(uintptr(slavefd), sname)
|
||||
t := os.NewFile(uintptr(ptsfd), sname)
|
||||
|
||||
// In case of error after this point, make sure we close the pts fd.
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = t.Close() // Best effort.
|
||||
}
|
||||
}()
|
||||
|
||||
// pushing terminal driver STREAMS modules as per pts(7)
|
||||
for _, mod := range([]string{"ptem", "ldterm", "ttcompat"}) {
|
||||
err = streams_push(t, mod)
|
||||
if err != nil {
|
||||
for _, mod := range []string{"ptem", "ldterm", "ttcompat"} {
|
||||
if err := streamsPush(t, mod); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return p, t, nil
|
||||
}
|
||||
|
||||
func minor(x uint64) uint64 {
|
||||
return x & 0377
|
||||
}
|
||||
|
||||
func ptsdev(fd uintptr) uint64 {
|
||||
istr := strioctl{ISPTM, 0, 0, nil}
|
||||
err := ioctl(fd, I_STR, uintptr(unsafe.Pointer(&istr)))
|
||||
if err != nil {
|
||||
return NODEV
|
||||
}
|
||||
var status unix.Stat_t
|
||||
err = unix.Fstat(int(fd), &status)
|
||||
if err != nil {
|
||||
return NODEV
|
||||
}
|
||||
return uint64(minor(status.Rdev))
|
||||
}
|
||||
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
dev := ptsdev(f.Fd())
|
||||
if dev == NODEV {
|
||||
return "", errors.New("not a master pty")
|
||||
dev, err := ptsdev(f.Fd())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fn := "/dev/pts/" + strconv.FormatInt(int64(dev), 10)
|
||||
// access(2) creates the slave device (if the pty exists)
|
||||
// F_OK == 0 (unistd.h)
|
||||
err := unix.Access(fn, 0)
|
||||
if err != nil {
|
||||
|
||||
if err := syscall.Access(fn, 0); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fn, nil
|
||||
}
|
||||
|
||||
type pt_own struct {
|
||||
pto_ruid int32
|
||||
pto_rgid int32
|
||||
func unlockpt(f *os.File) error {
|
||||
istr := strioctl{
|
||||
icCmd: UNLKPT,
|
||||
icTimeout: 0,
|
||||
icLen: 0,
|
||||
icDP: nil,
|
||||
}
|
||||
return ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr)))
|
||||
}
|
||||
|
||||
func minor(x uint64) uint64 { return x & 0377 }
|
||||
|
||||
func ptsdev(fd uintptr) (uint64, error) {
|
||||
istr := strioctl{
|
||||
icCmd: ISPTM,
|
||||
icTimeout: 0,
|
||||
icLen: 0,
|
||||
icDP: nil,
|
||||
}
|
||||
|
||||
if err := ioctl(fd, I_STR, uintptr(unsafe.Pointer(&istr))); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var status syscall.Stat_t
|
||||
if err := syscall.Fstat(int(fd), &status); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(minor(status.Rdev)), nil
|
||||
}
|
||||
|
||||
type ptOwn struct {
|
||||
rUID int32
|
||||
rGID int32
|
||||
}
|
||||
|
||||
func grantpt(f *os.File) error {
|
||||
if ptsdev(f.Fd()) == NODEV {
|
||||
return errors.New("not a master pty")
|
||||
if _, err := ptsdev(f.Fd()); err != nil {
|
||||
return err
|
||||
}
|
||||
var pto pt_own
|
||||
pto.pto_ruid = int32(os.Getuid())
|
||||
// XXX should first attempt to get gid of DEFAULT_TTY_GROUP="tty"
|
||||
pto.pto_rgid = int32(os.Getgid())
|
||||
var istr strioctl
|
||||
istr.ic_cmd = OWNERPT
|
||||
istr.ic_timout = 0
|
||||
istr.ic_len = int32(unsafe.Sizeof(istr))
|
||||
istr.ic_dp = unsafe.Pointer(&pto)
|
||||
err := ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr)))
|
||||
if err != nil {
|
||||
pto := ptOwn{
|
||||
rUID: int32(os.Getuid()),
|
||||
// XXX should first attempt to get gid of DEFAULT_TTY_GROUP="tty"
|
||||
rGID: int32(os.Getgid()),
|
||||
}
|
||||
istr := strioctl{
|
||||
icCmd: OWNERPT,
|
||||
icTimeout: 0,
|
||||
icLen: int32(unsafe.Sizeof(strioctl{})),
|
||||
icDP: unsafe.Pointer(&pto),
|
||||
}
|
||||
if err := ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr))); err != nil {
|
||||
return errors.New("access denied")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unlockpt(f *os.File) error {
|
||||
istr := strioctl{UNLKPT, 0, 0, nil}
|
||||
return ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr)))
|
||||
}
|
||||
|
||||
// push STREAMS modules if not already done so
|
||||
func streams_push(f *os.File, mod string) error {
|
||||
var err error
|
||||
// streamsPush pushes STREAMS modules if not already done so.
|
||||
func streamsPush(f *os.File, mod string) error {
|
||||
buf := []byte(mod)
|
||||
|
||||
// XXX I_FIND is not returning an error when the module
|
||||
// is already pushed even though truss reports a return
|
||||
// value of 1. A bug in the Go Solaris syscall interface?
|
||||
@@ -129,11 +144,9 @@ func streams_push(f *os.File, mod string) error {
|
||||
// https://www.illumos.org/issues/9042
|
||||
// but since we are not using libc or XPG4.2, we should not be
|
||||
// double-pushing modules
|
||||
|
||||
err = ioctl(f.Fd(), I_FIND, uintptr(unsafe.Pointer(&buf[0])))
|
||||
if err != nil {
|
||||
|
||||
if err := ioctl(f.Fd(), I_FIND, uintptr(unsafe.Pointer(&buf[0]))); err != nil {
|
||||
return nil
|
||||
}
|
||||
err = ioctl(f.Fd(), I_PUSH, uintptr(unsafe.Pointer(&buf[0])))
|
||||
return err
|
||||
return ioctl(f.Fd(), I_PUSH, uintptr(unsafe.Pointer(&buf[0])))
|
||||
}
|
||||
|
||||
3
vendor/github.com/creack/pty/pty_unsupported.go
generated
vendored
3
vendor/github.com/creack/pty/pty_unsupported.go
generated
vendored
@@ -1,4 +1,5 @@
|
||||
// +build !linux,!darwin,!freebsd,!dragonfly,!openbsd,!solaris
|
||||
//go:build !linux && !darwin && !freebsd && !dragonfly && !netbsd && !openbsd && !solaris && !windows
|
||||
// +build !linux,!darwin,!freebsd,!dragonfly,!netbsd,!openbsd,!solaris,!windows
|
||||
|
||||
package pty
|
||||
|
||||
|
||||
187
vendor/github.com/creack/pty/pty_windows.go
generated
vendored
Normal file
187
vendor/github.com/creack/pty/pty_windows.go
generated
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE = 0x20016
|
||||
)
|
||||
|
||||
type WindowsPty struct {
|
||||
handle windows.Handle
|
||||
r, w *os.File
|
||||
}
|
||||
|
||||
type WindowsTty struct {
|
||||
handle windows.Handle
|
||||
r, w *os.File
|
||||
}
|
||||
|
||||
var (
|
||||
// NOTE(security): as noted by the comment of syscall.NewLazyDLL and syscall.LoadDLL
|
||||
// user need to call internal/syscall/windows/sysdll.Add("kernel32.dll") to make sure
|
||||
// the kernel32.dll is loaded from windows system path
|
||||
//
|
||||
// ref: https://pkg.go.dev/syscall@go1.13?GOOS=windows#LoadDLL
|
||||
kernel32DLL = windows.NewLazyDLL("kernel32.dll")
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/console/createpseudoconsole
|
||||
createPseudoConsole = kernel32DLL.NewProc("CreatePseudoConsole")
|
||||
closePseudoConsole = kernel32DLL.NewProc("ClosePseudoConsole")
|
||||
|
||||
resizePseudoConsole = kernel32DLL.NewProc("ResizePseudoConsole")
|
||||
getConsoleScreenBufferInfo = kernel32DLL.NewProc("GetConsoleScreenBufferInfo")
|
||||
)
|
||||
|
||||
func open() (_ Pty, _ Tty, err error) {
|
||||
pr, consoleW, err := os.Pipe()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
consoleR, pw, err := os.Pipe()
|
||||
if err != nil {
|
||||
_ = consoleW.Close()
|
||||
_ = pr.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var consoleHandle windows.Handle
|
||||
|
||||
err = procCreatePseudoConsole(windows.Handle(consoleR.Fd()), windows.Handle(consoleW.Fd()),
|
||||
0, &consoleHandle)
|
||||
if err != nil {
|
||||
_ = consoleW.Close()
|
||||
_ = pr.Close()
|
||||
_ = pw.Close()
|
||||
_ = consoleR.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// These pipes can be closed here without any worry
|
||||
err = consoleW.Close()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to close pseudo console handle: %w", err)
|
||||
}
|
||||
|
||||
err = consoleR.Close()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to close pseudo console handle: %w", err)
|
||||
}
|
||||
|
||||
return &WindowsPty{
|
||||
handle: consoleHandle,
|
||||
r: pr,
|
||||
w: pw,
|
||||
}, &WindowsTty{
|
||||
handle: consoleHandle,
|
||||
r: consoleR,
|
||||
w: consoleW,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *WindowsPty) Name() string {
|
||||
return p.r.Name()
|
||||
}
|
||||
|
||||
func (p *WindowsPty) Fd() uintptr {
|
||||
return uintptr(p.handle)
|
||||
}
|
||||
|
||||
func (p *WindowsPty) Read(data []byte) (int, error) {
|
||||
return p.r.Read(data)
|
||||
}
|
||||
|
||||
func (p *WindowsPty) Write(data []byte) (int, error) {
|
||||
return p.w.Write(data)
|
||||
}
|
||||
|
||||
func (p *WindowsPty) WriteString(s string) (int, error) {
|
||||
return p.w.WriteString(s)
|
||||
}
|
||||
|
||||
func (p *WindowsPty) UpdateProcThreadAttribute(attrList *windows.ProcThreadAttributeListContainer) error {
|
||||
var err error
|
||||
|
||||
if err = attrList.Update(
|
||||
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
|
||||
unsafe.Pointer(p.handle),
|
||||
unsafe.Sizeof(p.handle),
|
||||
); err != nil {
|
||||
return fmt.Errorf("failed to update proc thread attributes for pseudo console: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *WindowsPty) Close() error {
|
||||
_ = p.r.Close()
|
||||
_ = p.w.Close()
|
||||
|
||||
err := closePseudoConsole.Find()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = closePseudoConsole.Call(uintptr(p.handle))
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *WindowsTty) Name() string {
|
||||
return t.r.Name()
|
||||
}
|
||||
|
||||
func (t *WindowsTty) Fd() uintptr {
|
||||
return uintptr(t.handle)
|
||||
}
|
||||
|
||||
func (t *WindowsTty) Read(p []byte) (int, error) {
|
||||
return t.r.Read(p)
|
||||
}
|
||||
|
||||
func (t *WindowsTty) Write(p []byte) (int, error) {
|
||||
return t.w.Write(p)
|
||||
}
|
||||
|
||||
func (t *WindowsTty) Close() error {
|
||||
_ = t.r.Close()
|
||||
return t.w.Close()
|
||||
}
|
||||
|
||||
func procCreatePseudoConsole(hInput windows.Handle, hOutput windows.Handle, dwFlags uint32, consoleHandle *windows.Handle) error {
|
||||
var r0 uintptr
|
||||
var err error
|
||||
|
||||
err = createPseudoConsole.Find()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r0, _, err = createPseudoConsole.Call(
|
||||
(windowsCoord{X: 80, Y: 30}).Pack(), // size: default 80x30 window
|
||||
uintptr(hInput), // console input
|
||||
uintptr(hOutput), // console output
|
||||
uintptr(dwFlags), // console flags, currently only PSEUDOCONSOLE_INHERIT_CURSOR supported
|
||||
uintptr(unsafe.Pointer(consoleHandle)), // console handler value return
|
||||
)
|
||||
|
||||
if int32(r0) < 0 {
|
||||
if r0&0x1fff0000 == 0x00070000 {
|
||||
r0 &= 0xffff
|
||||
}
|
||||
|
||||
// S_OK: 0
|
||||
return syscall.Errno(r0)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
64
vendor/github.com/creack/pty/run.go
generated
vendored
64
vendor/github.com/creack/pty/run.go
generated
vendored
@@ -1,11 +1,7 @@
|
||||
// +build !windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
|
||||
@@ -13,62 +9,6 @@ import (
|
||||
// corresponding pty.
|
||||
//
|
||||
// Starts the process in a new session and sets the controlling terminal.
|
||||
func Start(c *exec.Cmd) (pty *os.File, err error) {
|
||||
return StartWithSize(c, nil)
|
||||
}
|
||||
|
||||
// StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
|
||||
// and c.Stderr, calls c.Start, and returns the File of the tty's
|
||||
// corresponding pty.
|
||||
//
|
||||
// This will resize the pty to the specified size before starting the command.
|
||||
// Starts the process in a new session and sets the controlling terminal.
|
||||
func StartWithSize(c *exec.Cmd, sz *Winsize) (pty *os.File, err error) {
|
||||
if c.SysProcAttr == nil {
|
||||
c.SysProcAttr = &syscall.SysProcAttr{}
|
||||
}
|
||||
c.SysProcAttr.Setsid = true
|
||||
c.SysProcAttr.Setctty = true
|
||||
return StartWithAttrs(c, sz, c.SysProcAttr)
|
||||
}
|
||||
|
||||
// StartWithAttrs assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
|
||||
// and c.Stderr, calls c.Start, and returns the File of the tty's
|
||||
// corresponding pty.
|
||||
//
|
||||
// This will resize the pty to the specified size before starting the command if a size is provided.
|
||||
// The `attrs` parameter overrides the one set in c.SysProcAttr.
|
||||
//
|
||||
// This should generally not be needed. Used in some edge cases where it is needed to create a pty
|
||||
// without a controlling terminal.
|
||||
func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (pty *os.File, err error) {
|
||||
pty, tty, err := Open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tty.Close()
|
||||
|
||||
if sz != nil {
|
||||
if err := Setsize(pty, sz); err != nil {
|
||||
pty.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if c.Stdout == nil {
|
||||
c.Stdout = tty
|
||||
}
|
||||
if c.Stderr == nil {
|
||||
c.Stderr = tty
|
||||
}
|
||||
if c.Stdin == nil {
|
||||
c.Stdin = tty
|
||||
}
|
||||
|
||||
c.SysProcAttr = attrs
|
||||
|
||||
if err := c.Start(); err != nil {
|
||||
_ = pty.Close()
|
||||
return nil, err
|
||||
}
|
||||
return pty, err
|
||||
func Start(cmd *exec.Cmd) (Pty, error) {
|
||||
return StartWithSize(cmd, nil)
|
||||
}
|
||||
|
||||
69
vendor/github.com/creack/pty/run_unix.go
generated
vendored
Normal file
69
vendor/github.com/creack/pty/run_unix.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// StartWithSize assigns a pseudo-terminal Tty to c.Stdin, c.Stdout,
|
||||
// and c.Stderr, calls c.Start, and returns the File of the tty's
|
||||
// corresponding Pty.
|
||||
//
|
||||
// This will resize the Pty to the specified size before starting the command.
|
||||
// Starts the process in a new session and sets the controlling terminal.
|
||||
func StartWithSize(c *exec.Cmd, sz *Winsize) (Pty, error) {
|
||||
if c.SysProcAttr == nil {
|
||||
c.SysProcAttr = &syscall.SysProcAttr{}
|
||||
}
|
||||
c.SysProcAttr.Setsid = true
|
||||
c.SysProcAttr.Setctty = true
|
||||
return StartWithAttrs(c, sz, c.SysProcAttr)
|
||||
}
|
||||
|
||||
// StartWithAttrs assigns a pseudo-terminal Tty to c.Stdin, c.Stdout,
|
||||
// and c.Stderr, calls c.Start, and returns the File of the tty's
|
||||
// corresponding Pty.
|
||||
//
|
||||
// This will resize the Pty to the specified size before starting the command if a size is provided.
|
||||
// The `attrs` parameter overrides the one set in c.SysProcAttr.
|
||||
//
|
||||
// This should generally not be needed. Used in some edge cases where it is needed to create a pty
|
||||
// without a controlling terminal.
|
||||
func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (Pty, error) {
|
||||
pty, tty, err := open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
// always close tty fds since it's being used in another process
|
||||
// but pty is kept to resize tty
|
||||
_ = tty.Close()
|
||||
}()
|
||||
|
||||
if sz != nil {
|
||||
if err := Setsize(pty, sz); err != nil {
|
||||
_ = pty.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if c.Stdout == nil {
|
||||
c.Stdout = tty
|
||||
}
|
||||
if c.Stderr == nil {
|
||||
c.Stderr = tty
|
||||
}
|
||||
if c.Stdin == nil {
|
||||
c.Stdin = tty
|
||||
}
|
||||
|
||||
c.SysProcAttr = attrs
|
||||
|
||||
if err := c.Start(); err != nil {
|
||||
_ = pty.Close()
|
||||
return nil, err
|
||||
}
|
||||
return pty, err
|
||||
}
|
||||
230
vendor/github.com/creack/pty/run_windows.go
generated
vendored
Normal file
230
vendor/github.com/creack/pty/run_windows.go
generated
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// StartWithSize assigns a pseudo-terminal Tty to c.Stdin, c.Stdout,
|
||||
// and c.Stderr, calls c.Start, and returns the File of the tty's
|
||||
// corresponding Pty.
|
||||
//
|
||||
// This will resize the Pty to the specified size before starting the command.
|
||||
// Starts the process in a new session and sets the controlling terminal.
|
||||
func StartWithSize(c *exec.Cmd, sz *Winsize) (Pty, error) {
|
||||
return StartWithAttrs(c, sz, c.SysProcAttr)
|
||||
}
|
||||
|
||||
// StartWithAttrs assigns a pseudo-terminal Tty to c.Stdin, c.Stdout,
|
||||
// and c.Stderr, calls c.Start, and returns the File of the tty's
|
||||
// corresponding Pty.
|
||||
//
|
||||
// This will resize the Pty to the specified size before starting the command if a size is provided.
|
||||
// The `attrs` parameter overrides the one set in c.SysProcAttr.
|
||||
//
|
||||
// This should generally not be needed. Used in some edge cases where it is needed to create a pty
|
||||
// without a controlling terminal.
|
||||
func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (Pty, error) {
|
||||
pty, _, err := open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// unlike unix command exec, do not close tty unless error happened
|
||||
if err != nil {
|
||||
_ = pty.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if sz != nil {
|
||||
if err = Setsize(pty, sz); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// unlike unix command exec, do not set stdin/stdout/stderr
|
||||
|
||||
c.SysProcAttr = attrs
|
||||
|
||||
// do not use os/exec.Start since we need to append console handler to startup info
|
||||
|
||||
w := windowExecCmd{
|
||||
cmd: c,
|
||||
waitCalled: false,
|
||||
conPty: pty.(*WindowsPty),
|
||||
}
|
||||
|
||||
err = w.Start()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pty, err
|
||||
}
|
||||
|
||||
// Start the specified command but does not wait for it to complete.
|
||||
//
|
||||
// If Start returns successfully, the c.Process field will be set.
|
||||
//
|
||||
// The Wait method will return the exit code and release associated resources
|
||||
// once the command exits.
|
||||
func (c *windowExecCmd) Start() error {
|
||||
if c.cmd.Process != nil {
|
||||
return errors.New("exec: already started")
|
||||
}
|
||||
|
||||
var argv0 = c.cmd.Path
|
||||
var argv0p *uint16
|
||||
var argvp *uint16
|
||||
var dirp *uint16
|
||||
var err error
|
||||
|
||||
sys := c.cmd.SysProcAttr
|
||||
if sys == nil {
|
||||
sys = &syscall.SysProcAttr{}
|
||||
}
|
||||
|
||||
if c.cmd.Env == nil {
|
||||
c.cmd.Env, err = execEnvDefault(sys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var lp string
|
||||
|
||||
lp, err = lookExtensions(c.cmd.Path, c.cmd.Dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.cmd.Path = lp
|
||||
|
||||
if len(c.cmd.Dir) != 0 {
|
||||
// Windows CreateProcess looks for argv0 relative to the current
|
||||
// directory, and, only once the new process is started, it does
|
||||
// Chdir(attr.Dir). We are adjusting for that difference here by
|
||||
// making argv0 absolute.
|
||||
|
||||
argv0, err = joinExeDirAndFName(c.cmd.Dir, c.cmd.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
argv0p, err = syscall.UTF16PtrFromString(argv0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var cmdline string
|
||||
|
||||
// Windows CreateProcess takes the command line as a single string:
|
||||
// use attr.CmdLine if set, else build the command line by escaping
|
||||
// and joining each argument with spaces
|
||||
if sys.CmdLine != "" {
|
||||
cmdline = sys.CmdLine
|
||||
} else {
|
||||
cmdline = makeCmdLine(c.argv())
|
||||
}
|
||||
|
||||
if len(cmdline) != 0 {
|
||||
argvp, err = windows.UTF16PtrFromString(cmdline)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.cmd.Dir) != 0 {
|
||||
dirp, err = windows.UTF16PtrFromString(c.cmd.Dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Acquire the fork lock so that no other threads
|
||||
// create new fds that are not yet close-on-exec
|
||||
// before we fork.
|
||||
syscall.ForkLock.Lock()
|
||||
defer syscall.ForkLock.Unlock()
|
||||
|
||||
siEx := new(windows.StartupInfoEx)
|
||||
siEx.Flags = windows.STARTF_USESTDHANDLES
|
||||
|
||||
if sys.HideWindow {
|
||||
siEx.Flags |= syscall.STARTF_USESHOWWINDOW
|
||||
siEx.ShowWindow = syscall.SW_HIDE
|
||||
}
|
||||
|
||||
pi := new(windows.ProcessInformation)
|
||||
|
||||
// Need EXTENDED_STARTUPINFO_PRESENT as we're making use of the attribute list field.
|
||||
flags := sys.CreationFlags | uint32(windows.CREATE_UNICODE_ENVIRONMENT) | windows.EXTENDED_STARTUPINFO_PRESENT
|
||||
|
||||
c.attrList, err = windows.NewProcThreadAttributeList(1)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize process thread attribute list: %w", err)
|
||||
}
|
||||
|
||||
if c.conPty != nil {
|
||||
if err = c.conPty.UpdateProcThreadAttribute(c.attrList); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
siEx.ProcThreadAttributeList = c.attrList.List()
|
||||
siEx.Cb = uint32(unsafe.Sizeof(*siEx))
|
||||
|
||||
if sys.Token != 0 {
|
||||
err = windows.CreateProcessAsUser(
|
||||
windows.Token(sys.Token),
|
||||
argv0p,
|
||||
argvp,
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
flags,
|
||||
createEnvBlock(addCriticalEnv(dedupEnvCase(true, c.cmd.Env))),
|
||||
dirp,
|
||||
&siEx.StartupInfo,
|
||||
pi,
|
||||
)
|
||||
} else {
|
||||
err = windows.CreateProcess(
|
||||
argv0p,
|
||||
argvp,
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
flags,
|
||||
createEnvBlock(addCriticalEnv(dedupEnvCase(true, c.cmd.Env))),
|
||||
dirp,
|
||||
&siEx.StartupInfo,
|
||||
pi,
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = windows.CloseHandle(pi.Thread)
|
||||
}()
|
||||
|
||||
c.cmd.Process, err = os.FindProcess(int(pi.ProcessId))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
50
vendor/github.com/creack/pty/test_crosscompile.sh
generated
vendored
50
vendor/github.com/creack/pty/test_crosscompile.sh
generated
vendored
@@ -4,47 +4,59 @@
|
||||
# Does not actually test the logic, just the compilation so we make sure we don't break code depending on the lib.
|
||||
|
||||
echo2() {
|
||||
echo $@ >&2
|
||||
echo $@ >&2
|
||||
}
|
||||
|
||||
trap end 0
|
||||
end() {
|
||||
[ "$?" = 0 ] && echo2 "Pass." || (echo2 "Fail."; exit 1)
|
||||
[ "$?" = 0 ] && echo2 "Pass." || (echo2 "Fail."; exit 1)
|
||||
}
|
||||
|
||||
cross() {
|
||||
os=$1
|
||||
shift
|
||||
echo2 "Build for $os."
|
||||
for arch in $@; do
|
||||
echo2 " - $os/$arch"
|
||||
GOOS=$os GOARCH=$arch go build
|
||||
done
|
||||
echo2
|
||||
os=$1
|
||||
shift
|
||||
echo2 "Build for $os."
|
||||
for arch in $@; do
|
||||
echo2 " - $os/$arch"
|
||||
GOOS=$os GOARCH=$arch go build
|
||||
done
|
||||
echo2
|
||||
}
|
||||
|
||||
set -e
|
||||
|
||||
cross linux amd64 386 arm arm64 ppc64 ppc64le s390x mips mipsle mips64 mips64le
|
||||
cross darwin amd64 386 arm arm64
|
||||
cross freebsd amd64 386 arm
|
||||
cross netbsd amd64 386 arm
|
||||
cross darwin amd64 arm64
|
||||
cross freebsd amd64 386 arm arm64
|
||||
cross netbsd amd64 386 arm arm64
|
||||
cross openbsd amd64 386 arm arm64
|
||||
cross dragonfly amd64
|
||||
cross solaris amd64
|
||||
|
||||
# Not expected to work but should still compile.
|
||||
cross windows amd64 386 arm
|
||||
cross windows amd64 386 arm
|
||||
|
||||
# TODO: Fix compilation error on openbsd/arm.
|
||||
# TODO: Merge the solaris PR.
|
||||
|
||||
# Some os/arch require a different compiler. Run in docker.
|
||||
if ! hash docker; then
|
||||
# If docker is not present, stop here.
|
||||
return
|
||||
# If docker is not present, stop here.
|
||||
return
|
||||
fi
|
||||
|
||||
echo2 "Build for linux."
|
||||
echo2 " - linux/riscv"
|
||||
docker build -t test -f Dockerfile.riscv .
|
||||
docker build -t creack-pty-test -f Dockerfile.riscv .
|
||||
|
||||
# Golang dropped support for darwin 32bits since go1.15. Make sure the lib still compile with go1.14 on those archs.
|
||||
echo2 "Build for darwin (32bits)."
|
||||
echo2 " - darwin/386"
|
||||
docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.14 --build-arg=GOOS=darwin --build-arg=GOARCH=386 .
|
||||
echo2 " - darwin/arm"
|
||||
docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.14 --build-arg=GOOS=darwin --build-arg=GOARCH=arm .
|
||||
|
||||
# Run a single test for an old go version. Would be best with go1.0, but not available on Dockerhub.
|
||||
# Using 1.6 as it is the base version for the RISCV compiler.
|
||||
# Would also be better to run all the tests, not just one, need to refactor this file to allow for specifc archs per version.
|
||||
echo2 "Build for linux - go1.6."
|
||||
echo2 " - linux/amd64"
|
||||
docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.6 --build-arg=GOOS=linux --build-arg=GOARCH=amd64 .
|
||||
|
||||
64
vendor/github.com/creack/pty/util.go
generated
vendored
64
vendor/github.com/creack/pty/util.go
generated
vendored
@@ -1,64 +0,0 @@
|
||||
// +build !windows,!solaris
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// InheritSize applies the terminal size of pty to tty. This should be run
|
||||
// in a signal handler for syscall.SIGWINCH to automatically resize the tty when
|
||||
// the pty receives a window size change notification.
|
||||
func InheritSize(pty, tty *os.File) error {
|
||||
size, err := GetsizeFull(pty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = Setsize(tty, size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Setsize resizes t to s.
|
||||
func Setsize(t *os.File, ws *Winsize) error {
|
||||
return windowRectCall(ws, t.Fd(), syscall.TIOCSWINSZ)
|
||||
}
|
||||
|
||||
// GetsizeFull returns the full terminal size description.
|
||||
func GetsizeFull(t *os.File) (size *Winsize, err error) {
|
||||
var ws Winsize
|
||||
err = windowRectCall(&ws, t.Fd(), syscall.TIOCGWINSZ)
|
||||
return &ws, err
|
||||
}
|
||||
|
||||
// Getsize returns the number of rows (lines) and cols (positions
|
||||
// in each line) in terminal t.
|
||||
func Getsize(t *os.File) (rows, cols int, err error) {
|
||||
ws, err := GetsizeFull(t)
|
||||
return int(ws.Rows), int(ws.Cols), err
|
||||
}
|
||||
|
||||
// Winsize describes the terminal size.
|
||||
type Winsize struct {
|
||||
Rows uint16 // ws_row: Number of rows (in cells)
|
||||
Cols uint16 // ws_col: Number of columns (in cells)
|
||||
X uint16 // ws_xpixel: Width in pixels
|
||||
Y uint16 // ws_ypixel: Height in pixels
|
||||
}
|
||||
|
||||
func windowRectCall(ws *Winsize, fd, a2 uintptr) error {
|
||||
_, _, errno := syscall.Syscall(
|
||||
syscall.SYS_IOCTL,
|
||||
fd,
|
||||
a2,
|
||||
uintptr(unsafe.Pointer(ws)),
|
||||
)
|
||||
if errno != 0 {
|
||||
return syscall.Errno(errno)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
51
vendor/github.com/creack/pty/util_solaris.go
generated
vendored
51
vendor/github.com/creack/pty/util_solaris.go
generated
vendored
@@ -1,51 +0,0 @@
|
||||
//
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
TIOCGWINSZ = 21608 // 'T' << 8 | 104
|
||||
TIOCSWINSZ = 21607 // 'T' << 8 | 103
|
||||
)
|
||||
|
||||
// Winsize describes the terminal size.
|
||||
type Winsize struct {
|
||||
Rows uint16 // ws_row: Number of rows (in cells)
|
||||
Cols uint16 // ws_col: Number of columns (in cells)
|
||||
X uint16 // ws_xpixel: Width in pixels
|
||||
Y uint16 // ws_ypixel: Height in pixels
|
||||
}
|
||||
|
||||
// GetsizeFull returns the full terminal size description.
|
||||
func GetsizeFull(t *os.File) (size *Winsize, err error) {
|
||||
var wsz *unix.Winsize
|
||||
wsz, err = unix.IoctlGetWinsize(int(t.Fd()), TIOCGWINSZ)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return &Winsize{wsz.Row, wsz.Col, wsz.Xpixel, wsz.Ypixel}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get Windows Size
|
||||
func Getsize(t *os.File) (rows, cols int, err error) {
|
||||
var wsz *unix.Winsize
|
||||
wsz, err = unix.IoctlGetWinsize(int(t.Fd()), TIOCGWINSZ)
|
||||
|
||||
if err != nil {
|
||||
return 80, 25, err
|
||||
} else {
|
||||
return int(wsz.Row), int(wsz.Col), nil
|
||||
}
|
||||
}
|
||||
|
||||
// Setsize resizes t to s.
|
||||
func Setsize(t *os.File, ws *Winsize) error {
|
||||
wsz := unix.Winsize{ws.Rows, ws.Cols, ws.X, ws.Y}
|
||||
return unix.IoctlSetWinsize(int(t.Fd()), TIOCSWINSZ, &wsz)
|
||||
}
|
||||
31
vendor/github.com/creack/pty/winsize.go
generated
vendored
Normal file
31
vendor/github.com/creack/pty/winsize.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package pty
|
||||
|
||||
// Winsize describes the terminal size.
|
||||
type Winsize struct {
|
||||
Rows uint16 // ws_row: Number of rows (in cells)
|
||||
Cols uint16 // ws_col: Number of columns (in cells)
|
||||
X uint16 // ws_xpixel: Width in pixels
|
||||
Y uint16 // ws_ypixel: Height in pixels
|
||||
}
|
||||
|
||||
// InheritSize applies the terminal size of pty to tty. This should be run
|
||||
// in a signal handler for syscall.SIGWINCH to automatically resize the tty when
|
||||
// the pty receives a window size change notification.
|
||||
func InheritSize(pty Pty, tty Tty) error {
|
||||
size, err := GetsizeFull(pty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := Setsize(tty, size); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Getsize returns the number of rows (lines) and cols (positions
|
||||
// in each line) in terminal t.
|
||||
func Getsize(t FdHolder) (rows, cols int, err error) {
|
||||
ws, err := GetsizeFull(t)
|
||||
return int(ws.Rows), int(ws.Cols), err
|
||||
}
|
||||
26
vendor/github.com/creack/pty/winsize_unix.go
generated
vendored
Normal file
26
vendor/github.com/creack/pty/winsize_unix.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Setsize resizes t to s.
|
||||
func Setsize(t FdHolder, ws *Winsize) error {
|
||||
//nolint:gosec // Expected unsafe pointer for Syscall call.
|
||||
return ioctl(t.Fd(), syscall.TIOCSWINSZ, uintptr(unsafe.Pointer(ws)))
|
||||
}
|
||||
|
||||
// GetsizeFull returns the full terminal size description.
|
||||
func GetsizeFull(t FdHolder) (size *Winsize, err error) {
|
||||
var ws Winsize
|
||||
|
||||
//nolint:gosec // Expected unsafe pointer for Syscall call.
|
||||
if err := ioctl(t.Fd(), syscall.TIOCGWINSZ, uintptr(unsafe.Pointer(&ws))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ws, nil
|
||||
}
|
||||
89
vendor/github.com/creack/pty/winsize_windows.go
generated
vendored
Normal file
89
vendor/github.com/creack/pty/winsize_windows.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// types from golang.org/x/sys/windows
|
||||
// copy of https://pkg.go.dev/golang.org/x/sys/windows#Coord
|
||||
type windowsCoord struct {
|
||||
X int16
|
||||
Y int16
|
||||
}
|
||||
|
||||
// copy of https://pkg.go.dev/golang.org/x/sys/windows#SmallRect
|
||||
type windowsSmallRect struct {
|
||||
Left int16
|
||||
Top int16
|
||||
Right int16
|
||||
Bottom int16
|
||||
}
|
||||
|
||||
// copy of https://pkg.go.dev/golang.org/x/sys/windows#ConsoleScreenBufferInfo
|
||||
type windowsConsoleScreenBufferInfo struct {
|
||||
Size windowsCoord
|
||||
CursorPosition windowsCoord
|
||||
Attributes uint16
|
||||
Window windowsSmallRect
|
||||
MaximumWindowSize windowsCoord
|
||||
}
|
||||
|
||||
func (c windowsCoord) Pack() uintptr {
|
||||
return uintptr((int32(c.Y) << 16) | int32(c.X))
|
||||
}
|
||||
|
||||
// Setsize resizes t to ws.
|
||||
func Setsize(t FdHolder, ws *Winsize) error {
|
||||
var r0 uintptr
|
||||
var err error
|
||||
|
||||
err = resizePseudoConsole.Find()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r0, _, err = resizePseudoConsole.Call(
|
||||
t.Fd(),
|
||||
(windowsCoord{X: int16(ws.Cols), Y: int16(ws.Rows)}).Pack(),
|
||||
)
|
||||
if int32(r0) < 0 {
|
||||
if r0&0x1fff0000 == 0x00070000 {
|
||||
r0 &= 0xffff
|
||||
}
|
||||
|
||||
// S_OK: 0
|
||||
return syscall.Errno(r0)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetsizeFull returns the full terminal size description.
|
||||
func GetsizeFull(t FdHolder) (size *Winsize, err error) {
|
||||
err = getConsoleScreenBufferInfo.Find()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var info windowsConsoleScreenBufferInfo
|
||||
var r0 uintptr
|
||||
|
||||
r0, _, err = getConsoleScreenBufferInfo.Call(t.Fd(), uintptr(unsafe.Pointer(&info)))
|
||||
if int32(r0) < 0 {
|
||||
if r0&0x1fff0000 == 0x00070000 {
|
||||
r0 &= 0xffff
|
||||
}
|
||||
|
||||
// S_OK: 0
|
||||
return nil, syscall.Errno(r0)
|
||||
}
|
||||
|
||||
return &Winsize{
|
||||
Rows: uint16(info.Window.Bottom - info.Window.Top + 1),
|
||||
Cols: uint16(info.Window.Right - info.Window.Left + 1),
|
||||
}, nil
|
||||
}
|
||||
3
vendor/github.com/creack/pty/ztypes_386.go
generated
vendored
3
vendor/github.com/creack/pty/ztypes_386.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build 386
|
||||
// +build 386
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
|
||||
3
vendor/github.com/creack/pty/ztypes_amd64.go
generated
vendored
3
vendor/github.com/creack/pty/ztypes_amd64.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build amd64
|
||||
// +build amd64
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
|
||||
3
vendor/github.com/creack/pty/ztypes_arm.go
generated
vendored
3
vendor/github.com/creack/pty/ztypes_arm.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build arm
|
||||
// +build arm
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
|
||||
5
vendor/github.com/creack/pty/ztypes_arm64.go
generated
vendored
5
vendor/github.com/creack/pty/ztypes_arm64.go
generated
vendored
@@ -1,8 +1,9 @@
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
// +build arm64
|
||||
|
||||
package pty
|
||||
|
||||
type (
|
||||
|
||||
3
vendor/github.com/creack/pty/ztypes_dragonfly_amd64.go
generated
vendored
3
vendor/github.com/creack/pty/ztypes_dragonfly_amd64.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build amd64 && dragonfly
|
||||
// +build amd64,dragonfly
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_dragonfly.go
|
||||
|
||||
|
||||
3
vendor/github.com/creack/pty/ztypes_freebsd_386.go
generated
vendored
3
vendor/github.com/creack/pty/ztypes_freebsd_386.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build 386 && freebsd
|
||||
// +build 386,freebsd
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
|
||||
3
vendor/github.com/creack/pty/ztypes_freebsd_amd64.go
generated
vendored
3
vendor/github.com/creack/pty/ztypes_freebsd_amd64.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build amd64 && freebsd
|
||||
// +build amd64,freebsd
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
|
||||
3
vendor/github.com/creack/pty/ztypes_freebsd_arm.go
generated
vendored
3
vendor/github.com/creack/pty/ztypes_freebsd_arm.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build arm && freebsd
|
||||
// +build arm,freebsd
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
|
||||
3
vendor/github.com/creack/pty/ztypes_freebsd_arm64.go
generated
vendored
3
vendor/github.com/creack/pty/ztypes_freebsd_arm64.go
generated
vendored
@@ -1,3 +1,6 @@
|
||||
//go:build arm64 && freebsd
|
||||
// +build arm64,freebsd
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
|
||||
14
vendor/github.com/creack/pty/ztypes_freebsd_ppc64.go
generated
vendored
Normal file
14
vendor/github.com/creack/pty/ztypes_freebsd_ppc64.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
package pty
|
||||
|
||||
const (
|
||||
_C_SPECNAMELEN = 0x3f
|
||||
)
|
||||
|
||||
type fiodgnameArg struct {
|
||||
Len int32
|
||||
Pad_cgo_0 [4]byte
|
||||
Buf *byte
|
||||
}
|
||||
12
vendor/github.com/creack/pty/ztypes_loong64.go
generated
vendored
Normal file
12
vendor/github.com/creack/pty/ztypes_loong64.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build loong64
|
||||
// +build loong64
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
package pty
|
||||
|
||||
type (
|
||||
_C_int int32
|
||||
_C_uint uint32
|
||||
)
|
||||
7
vendor/github.com/creack/pty/ztypes_mipsx.go
generated
vendored
7
vendor/github.com/creack/pty/ztypes_mipsx.go
generated
vendored
@@ -1,9 +1,10 @@
|
||||
//go:build (mips || mipsle || mips64 || mips64le) && linux
|
||||
// +build mips mipsle mips64 mips64le
|
||||
// +build linux
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
// +build linux
|
||||
// +build mips mipsle mips64 mips64le
|
||||
|
||||
package pty
|
||||
|
||||
type (
|
||||
|
||||
17
vendor/github.com/creack/pty/ztypes_netbsd_32bit_int.go
generated
vendored
Normal file
17
vendor/github.com/creack/pty/ztypes_netbsd_32bit_int.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
//go:build (386 || amd64 || arm || arm64) && netbsd
|
||||
// +build 386 amd64 arm arm64
|
||||
// +build netbsd
|
||||
|
||||
package pty
|
||||
|
||||
type ptmget struct {
|
||||
Cfd int32
|
||||
Sfd int32
|
||||
Cn [1024]int8
|
||||
Sn [1024]int8
|
||||
}
|
||||
|
||||
var (
|
||||
ioctl_TIOCPTSNAME = 0x48087448
|
||||
ioctl_TIOCGRANTPT = 0x20007447
|
||||
)
|
||||
11
vendor/github.com/creack/pty/ztypes_openbsd_32bit_int.go
generated
vendored
11
vendor/github.com/creack/pty/ztypes_openbsd_32bit_int.go
generated
vendored
@@ -1,13 +1,14 @@
|
||||
//go:build (386 || amd64 || arm || arm64 || mips64) && openbsd
|
||||
// +build 386 amd64 arm arm64 mips64
|
||||
// +build openbsd
|
||||
// +build 386 amd64 arm arm64
|
||||
|
||||
package pty
|
||||
|
||||
type ptmget struct {
|
||||
Cfd int32
|
||||
Sfd int32
|
||||
Cn [16]int8
|
||||
Sn [16]int8
|
||||
Cfd int32
|
||||
Sfd int32
|
||||
Cn [16]int8
|
||||
Sn [16]int8
|
||||
}
|
||||
|
||||
var ioctl_PTMGET = 0x40287401
|
||||
|
||||
1
vendor/github.com/creack/pty/ztypes_ppc64.go
generated
vendored
1
vendor/github.com/creack/pty/ztypes_ppc64.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build ppc64
|
||||
// +build ppc64
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
|
||||
1
vendor/github.com/creack/pty/ztypes_ppc64le.go
generated
vendored
1
vendor/github.com/creack/pty/ztypes_ppc64le.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build ppc64le
|
||||
// +build ppc64le
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
|
||||
5
vendor/github.com/creack/pty/ztypes_riscvx.go
generated
vendored
5
vendor/github.com/creack/pty/ztypes_riscvx.go
generated
vendored
@@ -1,8 +1,9 @@
|
||||
//go:build riscv || riscv64
|
||||
// +build riscv riscv64
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types.go
|
||||
|
||||
// +build riscv riscv64
|
||||
|
||||
package pty
|
||||
|
||||
type (
|
||||
|
||||
1
vendor/github.com/creack/pty/ztypes_s390x.go
generated
vendored
1
vendor/github.com/creack/pty/ztypes_s390x.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build s390x
|
||||
// +build s390x
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
|
||||
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
@@ -13,7 +13,7 @@ github.com/cli/safeexec
|
||||
# github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
|
||||
## explicit
|
||||
github.com/cloudfoundry/jibber_jabber
|
||||
# github.com/creack/pty v1.1.11
|
||||
# github.com/creack/pty v1.1.11 => github.com/photostorm/pty v1.1.19-0.20230324012736-6794a5ba0ba0
|
||||
## explicit; go 1.13
|
||||
github.com/creack/pty
|
||||
# github.com/davecgh/go-spew v1.1.1
|
||||
@@ -320,3 +320,4 @@ gopkg.in/warnings.v0
|
||||
# gopkg.in/yaml.v3 v3.0.1
|
||||
## explicit
|
||||
gopkg.in/yaml.v3
|
||||
# github.com/creack/pty => github.com/photostorm/pty v1.1.19-0.20230324012736-6794a5ba0ba0
|
||||
|
||||
Reference in New Issue
Block a user