Skip to content

Commit df52b7a

Browse files
authored
Merge pull request #9 from cli/go-1.19-compat
Allow relative PATH entries on Go 1.19+
2 parents 7342e94 + e86b61c commit df52b7a

File tree

4 files changed

+65
-13
lines changed

4 files changed

+65
-13
lines changed

.github/workflows/go.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
fail-fast: false
1010
matrix:
1111
os: [ubuntu-latest, windows-latest]
12-
go: [1.13, 1.14, 1.15]
12+
go: [1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.20]
1313

1414
runs-on: ${{matrix.os}}
1515
steps:

lookpath.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
// +build !windows
1+
//go:build !windows && go1.19
2+
// +build !windows,go1.19
23

34
package safeexec
45

5-
import "os/exec"
6+
import (
7+
"errors"
8+
"os/exec"
9+
)
610

711
func LookPath(file string) (string, error) {
8-
return exec.LookPath(file)
12+
path, err := exec.LookPath(file)
13+
if errors.Is(err, exec.ErrDot) {
14+
return path, nil
15+
}
16+
return path, err
917
}

lookpath_1.18.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//go:build !windows && !go1.19
2+
// +build !windows,!go1.19
3+
4+
package safeexec
5+
6+
import "os/exec"
7+
8+
func LookPath(file string) (string, error) {
9+
return exec.LookPath(file)
10+
}

lookpath_test.go

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,97 +16,117 @@ func TestLookPath(t *testing.T) {
1616
t.Fatal(wderr)
1717
}
1818

19-
paths := []string{
20-
filepath.Join(root, "_fixtures", "nonexist"),
21-
filepath.Join(root, "_fixtures", "system"),
22-
}
23-
os.Setenv("PATH", strings.Join(paths, string(filepath.ListSeparator)))
24-
2519
if err := os.Chdir(filepath.Join(root, "_fixtures", "cwd")); err != nil {
2620
t.Fatal(err)
2721
}
2822

2923
testCases := []struct {
3024
desc string
25+
path []string
3126
pathext string
3227
arg string
3328
wants string
3429
wantErr bool
3530
}{
3631
{
37-
desc: "no extension",
32+
desc: "no extension",
33+
path: []string{
34+
filepath.Join(root, "_fixtures", "nonexist"),
35+
filepath.Join(root, "_fixtures", "system"),
36+
},
3837
pathext: "",
3938
arg: "ls",
4039
wants: filepath.Join(root, "_fixtures", "system", "ls"+winonly(".exe")),
4140
wantErr: false,
4241
},
4342
{
4443
desc: "with extension",
44+
path: []string{filepath.Join(root, "_fixtures", "system")},
4545
pathext: "",
4646
arg: "ls.exe",
4747
wants: filepath.Join(root, "_fixtures", "system", "ls.exe"),
4848
wantErr: false,
4949
},
5050
{
5151
desc: "with path",
52+
path: []string{filepath.Join(root, "_fixtures", "system")},
5253
pathext: "",
5354
arg: filepath.Join("..", "system", "ls"),
5455
wants: filepath.Join("..", "system", "ls"+winonly(".exe")),
5556
wantErr: false,
5657
},
5758
{
5859
desc: "with path+extension",
60+
path: []string{filepath.Join(root, "_fixtures", "system")},
5961
pathext: "",
6062
arg: filepath.Join("..", "system", "ls.bat"),
6163
wants: filepath.Join("..", "system", "ls.bat"),
6264
wantErr: false,
6365
},
6466
{
6567
desc: "no extension, PATHEXT",
68+
path: []string{filepath.Join(root, "_fixtures", "system")},
6669
pathext: ".com;.bat",
6770
arg: "ls",
6871
wants: filepath.Join(root, "_fixtures", "system", "ls"+winonly(".bat")),
6972
wantErr: false,
7073
},
7174
{
7275
desc: "with extension, PATHEXT",
76+
path: []string{filepath.Join(root, "_fixtures", "system")},
7377
pathext: ".com;.bat",
7478
arg: "ls.exe",
7579
wants: filepath.Join(root, "_fixtures", "system", "ls.exe"),
7680
wantErr: false,
7781
},
7882
{
79-
desc: "no extension, not found",
83+
desc: "no extension, not found",
84+
path: []string{
85+
filepath.Join(root, "_fixtures", "nonexist"),
86+
filepath.Join(root, "_fixtures", "system"),
87+
},
8088
pathext: "",
8189
arg: "cat",
8290
wants: "",
8391
wantErr: true,
8492
},
8593
{
8694
desc: "with extension, not found",
95+
path: []string{filepath.Join(root, "_fixtures", "system")},
8796
pathext: "",
8897
arg: "cat.exe",
8998
wants: "",
9099
wantErr: true,
91100
},
92101
{
93102
desc: "no extension, PATHEXT, not found",
103+
path: []string{filepath.Join(root, "_fixtures", "system")},
94104
pathext: ".com;.bat",
95105
arg: "cat",
96106
wants: "",
97107
wantErr: true,
98108
},
99109
{
100110
desc: "with extension, PATHEXT, not found",
111+
path: []string{filepath.Join(root, "_fixtures", "system")},
101112
pathext: ".com;.bat",
102113
arg: "cat.exe",
103114
wants: "",
104115
wantErr: true,
105116
},
117+
{
118+
desc: "relative path",
119+
path: []string{filepath.Join("..", "system")},
120+
pathext: "",
121+
arg: "ls",
122+
wants: filepath.Join("..", "system", "ls"+winonly(".exe")),
123+
wantErr: false,
124+
},
106125
}
107126
for _, tC := range testCases {
108127
t.Run(tC.desc, func(t *testing.T) {
109-
os.Setenv("PATHEXT", tC.pathext)
128+
setenv(t, "PATH", strings.Join(tC.path, string(filepath.ListSeparator)))
129+
setenv(t, "PATHEXT", tC.pathext)
110130
got, err := LookPath(tC.arg)
111131

112132
if tC.wantErr != (err != nil) {
@@ -122,6 +142,20 @@ func TestLookPath(t *testing.T) {
122142
}
123143
}
124144

145+
func setenv(t *testing.T, name, newValue string) {
146+
oldValue, hasOldValue := os.LookupEnv(name)
147+
if err := os.Setenv(name, newValue); err != nil {
148+
t.Errorf("error setting environment variable %s: %v", name, err)
149+
}
150+
t.Cleanup(func() {
151+
if hasOldValue {
152+
_ = os.Setenv(name, oldValue)
153+
} else {
154+
_ = os.Unsetenv(name)
155+
}
156+
})
157+
}
158+
125159
func winonly(s string) string {
126160
if runtime.GOOS == "windows" {
127161
return s

0 commit comments

Comments
 (0)