-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
testscript: respect TestScript env PATH variable for exec command (#49)
Includes a partial snapshot of os/exec's platform-specific LookPath logic, as of 0456036e28b718d215f49abe83d3c49101f8a4c7. This is largely a copy and paste, with a type alias to os/exec.Error and an "alias" of os/exec.ErrNotFound.
- Loading branch information
Showing
11 changed files
with
300 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package execpath | ||
|
||
import "os/exec" | ||
|
||
type Error = exec.Error | ||
|
||
// ErrNotFound is the error resulting if a path search failed to find an executable file. | ||
var ErrNotFound = exec.ErrNotFound |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright 2018 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. | ||
|
||
// +build js,wasm | ||
|
||
package execpath | ||
|
||
// Look searches for an executable named file, using getenv to look up | ||
// environment variables. If getenv is nil, os.Getenv will be used. If file | ||
// contains a slash, it is tried directly and getenv will not be called. The | ||
// result may be an absolute path or a path relative to the current directory. | ||
func Look(file string, getenv func(string) string) (string, error) { | ||
// Wasm can not execute processes, so act as if there are no executables at all. | ||
return "", &Error{file, ErrNotFound} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright 2011 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. | ||
|
||
package execpath | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
func findExecutable(file string) error { | ||
d, err := os.Stat(file) | ||
if err != nil { | ||
return err | ||
} | ||
if m := d.Mode(); !m.IsDir() && m&0111 != 0 { | ||
return nil | ||
} | ||
return os.ErrPermission | ||
} | ||
|
||
// Look searches for an executable named file, using getenv to look up | ||
// environment variables. If getenv is nil, os.Getenv will be used. If file | ||
// contains a slash, it is tried directly and getenv will not be called. The | ||
// result may be an absolute path or a path relative to the current directory. | ||
func Look(file string, getenv func(string) string) (string, error) { | ||
if getenv == nil { | ||
getenv = os.Getenv | ||
} | ||
|
||
// skip the path lookup for these prefixes | ||
skip := []string{"/", "#", "./", "../"} | ||
|
||
for _, p := range skip { | ||
if strings.HasPrefix(file, p) { | ||
err := findExecutable(file) | ||
if err == nil { | ||
return file, nil | ||
} | ||
return "", &Error{file, err} | ||
} | ||
} | ||
|
||
path := getenv("path") | ||
for _, dir := range filepath.SplitList(path) { | ||
path := filepath.Join(dir, file) | ||
if err := findExecutable(path); err == nil { | ||
return path, nil | ||
} | ||
} | ||
return "", &Error{file, ErrNotFound} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Copyright 2010 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. | ||
|
||
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris | ||
|
||
package execpath | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
func findExecutable(file string) error { | ||
d, err := os.Stat(file) | ||
if err != nil { | ||
return err | ||
} | ||
if m := d.Mode(); !m.IsDir() && m&0111 != 0 { | ||
return nil | ||
} | ||
return os.ErrPermission | ||
} | ||
|
||
// Look searches for an executable named file, using getenv to look up | ||
// environment variables. If getenv is nil, os.Getenv will be used. If file | ||
// contains a slash, it is tried directly and getenv will not be called. The | ||
// result may be an absolute path or a path relative to the current directory. | ||
func Look(file string, getenv func(string) string) (string, error) { | ||
if getenv == nil { | ||
getenv = os.Getenv | ||
} | ||
|
||
// NOTE(rsc): I wish we could use the Plan 9 behavior here | ||
// (only bypass the path if file begins with / or ./ or ../) | ||
// but that would not match all the Unix shells. | ||
|
||
if strings.Contains(file, "/") { | ||
err := findExecutable(file) | ||
if err == nil { | ||
return file, nil | ||
} | ||
return "", &Error{file, err} | ||
} | ||
path := getenv("PATH") | ||
for _, dir := range filepath.SplitList(path) { | ||
if dir == "" { | ||
// Unix shell semantics: path element "" means "." | ||
dir = "." | ||
} | ||
path := filepath.Join(dir, file) | ||
if err := findExecutable(path); err == nil { | ||
return path, nil | ||
} | ||
} | ||
return "", &Error{file, ErrNotFound} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// Copyright 2010 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. | ||
|
||
package execpath | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
func chkStat(file string) error { | ||
d, err := os.Stat(file) | ||
if err != nil { | ||
return err | ||
} | ||
if d.IsDir() { | ||
return os.ErrPermission | ||
} | ||
return nil | ||
} | ||
|
||
func hasExt(file string) bool { | ||
i := strings.LastIndex(file, ".") | ||
if i < 0 { | ||
return false | ||
} | ||
return strings.LastIndexAny(file, `:\/`) < i | ||
} | ||
|
||
func findExecutable(file string, exts []string) (string, error) { | ||
if len(exts) == 0 { | ||
return file, chkStat(file) | ||
} | ||
if hasExt(file) { | ||
if chkStat(file) == nil { | ||
return file, nil | ||
} | ||
} | ||
for _, e := range exts { | ||
if f := file + e; chkStat(f) == nil { | ||
return f, nil | ||
} | ||
} | ||
return "", os.ErrNotExist | ||
} | ||
|
||
// Look searches for an executable named file, using getenv to look up | ||
// environment variables. If getenv is nil, os.Getenv will be used. If file | ||
// contains a slash, it is tried directly and getenv will not be called. The | ||
// result may be an absolute path or a path relative to the current directory. | ||
// Look also uses PATHEXT environment variable to match | ||
// a suitable candidate. | ||
func Look(file string, getenv func(string) string) (string, error) { | ||
if getenv == nil { | ||
getenv = os.Getenv | ||
} | ||
var exts []string | ||
x := getenv(`PATHEXT`) | ||
if x != "" { | ||
for _, e := range strings.Split(strings.ToLower(x), `;`) { | ||
if e == "" { | ||
continue | ||
} | ||
if e[0] != '.' { | ||
e = "." + e | ||
} | ||
exts = append(exts, e) | ||
} | ||
} else { | ||
exts = []string{".com", ".exe", ".bat", ".cmd"} | ||
} | ||
|
||
if strings.ContainsAny(file, `:\/`) { | ||
if f, err := findExecutable(file, exts); err == nil { | ||
return f, nil | ||
} else { | ||
return "", &Error{file, err} | ||
} | ||
} | ||
if f, err := findExecutable(filepath.Join(".", file), exts); err == nil { | ||
return f, nil | ||
} | ||
path := getenv("path") | ||
for _, dir := range filepath.SplitList(path) { | ||
if f, err := findExecutable(filepath.Join(dir, file), exts); err == nil { | ||
return f, nil | ||
} | ||
} | ||
return "", &Error{file, ErrNotFound} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// +build !windows | ||
|
||
package testscript | ||
|
||
func envvarname(k string) string { | ||
return k | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package testscript | ||
|
||
import "strings" | ||
|
||
func envvarname(k string) string { | ||
return strings.ToLower(k) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# If the PATH environment variable is set in the testscript.Params.Setup phase | ||
# or set directly within a script, exec should honour that PATH | ||
|
||
[!windows] env HOME=$WORK/home | ||
[windows] env HOME=$WORK\home | ||
[windows] env USERPROFILE=$WORK\home | ||
[windows] env LOCALAPPDATA=$WORK\appdata | ||
|
||
cd go | ||
exec go$exe version | ||
stdout 'go version' | ||
exec go$exe build | ||
[!windows] env PATH=$WORK/go${:}$PATH | ||
[windows] env PATH=$WORK\go${:}$PATH | ||
exec go$exe version | ||
stdout 'This is not go' | ||
|
||
-- go/main.go -- | ||
package main | ||
|
||
import "fmt" | ||
|
||
func main() { | ||
fmt.Println("This is not go") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
[exec:nosuchcommand] exec nosuchcommand | ||
[exec:cat] exec cat foo | ||
[exec:cat] stdout 'foo\n' | ||
[!exec:cat] grep 'foo\n' foo | ||
[!exec:cat] stop | ||
exec cat foo | ||
stdout 'foo\n' | ||
|
||
-- foo -- | ||
foo |
Oops, something went wrong.