Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix and test builds for GOOS=plan9 #1109

Merged
merged 2 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ jobs:
CGO_ENABLED=0 go test -run TestRunnerRunConfirm -exec 'dockexec bash:5.2' ./interp
if: matrix.os == 'ubuntu-latest'

# Test that we can build for platforms that we can't currently test on.
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.23.x'
run: |
GOOS=plan9 GOARCH=amd64 go build ./...
GOOS=js GOARCH=wasm go build ./...

# Static checks from this point forward. Only run on one Go version and on
# Linux, since it's the fastest platform, and the tools behave the same.
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.23.x'
Expand Down
5 changes: 1 addition & 4 deletions expand/expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"runtime"
"strconv"
"strings"
"syscall"

"mvdan.cc/sh/v3/pattern"
"mvdan.cc/sh/v3/syntax"
Expand Down Expand Up @@ -890,9 +889,7 @@ func (cfg *Config) glob(base, pat string) ([]string, error) {
// which can be wasteful if we only want to see if it exists,
// but at least it's correct in all scenarios.
if _, err := cfg.ReadDir2(match); err != nil {
const errPathNotFound = syscall.Errno(3) // from syscall/types_windows.go, to avoid a build tag
var pathErr *os.PathError
if runtime.GOOS == "windows" && errors.As(err, &pathErr) && pathErr.Err == errPathNotFound {
if isWindowsErrPathNotFound(err) {
// Unfortunately, os.File.Readdir on a regular file on
// Windows returns an error that satisfies ErrNotExist.
// Luckily, it returns a special "path not found" rather
Expand Down
8 changes: 8 additions & 0 deletions expand/expand_nonwindows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2017, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

//go:build !windows

package expand

func isWindowsErrPathNotFound(error) bool { return false }
15 changes: 15 additions & 0 deletions expand/expand_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) 2017, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package expand

import (
"errors"
"os"
"syscall"
)

func isWindowsErrPathNotFound(err error) bool {
var pathErr *os.PathError
return errors.As(err, &pathErr) && pathErr.Err == syscall.ERROR_PATH_NOT_FOUND
}
18 changes: 7 additions & 11 deletions interp/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"path/filepath"
"runtime"
"strings"
"syscall"
"time"

"mvdan.cc/sh/v3/expand"
Expand Down Expand Up @@ -135,18 +134,15 @@ func DefaultExecHandler(killTimeout time.Duration) ExecHandlerFunc {

switch err := err.(type) {
case *exec.ExitError:
// started, but errored - default to 1 if OS
// doesn't have exit statuses
if status, ok := err.Sys().(syscall.WaitStatus); ok {
if status.Signaled() {
if ctx.Err() != nil {
return ctx.Err()
}
return NewExitStatus(uint8(128 + status.Signal()))
// Windows and Plan9 do not have support for syscall.WaitStatus
// with methods like Signaled and Signal, so for those, waitStatus is a no-op.
if status, ok := err.Sys().(waitStatus); ok && status.Signaled() {
if ctx.Err() != nil {
return ctx.Err()
}
return NewExitStatus(uint8(status.ExitStatus()))
return NewExitStatus(uint8(128 + status.Signal()))
}
return NewExitStatus(1)
return NewExitStatus(uint8(err.ExitCode()))
case *exec.Error:
// did not start
fmt.Fprintf(hc.Stderr, "%v\n", err)
Expand Down
6 changes: 6 additions & 0 deletions interp/os_notunix.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ func hasPermissionToDir(string) bool {
func (r *Runner) unTestOwnOrGrp(ctx context.Context, op syntax.UnTestOperator, x string) bool {
panic(fmt.Sprintf("unhandled unary test op: %v", op))
}

// waitStatus is a no-op on plan9 and windows.
type waitStatus struct{}

func (waitStatus) Signaled() bool { return false }
func (waitStatus) Signal() int { return 0 }
2 changes: 2 additions & 0 deletions interp/os_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ func (r *Runner) unTestOwnOrGrp(ctx context.Context, op syntax.UnTestOperator, x
gid, _ := strconv.Atoi(u.Gid)
return uint32(gid) == info.Sys().(*syscall.Stat_t).Gid
}

type waitStatus = syscall.WaitStatus