Preserve child working directory in environment overlays
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -151,14 +150,15 @@ func newCommand(ctx context.Context, invocation Invocation) (*exec.Cmd, error) {
|
||||
command.Dir = invocation.Dir
|
||||
command.WaitDelay = time.Second
|
||||
if len(invocation.Env) != 0 || len(invocation.UnsetEnv) != 0 {
|
||||
command.Env = environmentEntries(invocation.Env, invocation.UnsetEnv)
|
||||
// Dir contributes PWD on POSIX before explicit overrides are applied.
|
||||
command.Env = environmentEntries(command.Environ(), invocation.Env, invocation.UnsetEnv)
|
||||
}
|
||||
return command, nil
|
||||
}
|
||||
|
||||
func environmentEntries(overlay map[string]string, unset []string) []string {
|
||||
environment := make(map[string]string, len(os.Environ())+len(overlay))
|
||||
for _, entry := range os.Environ() {
|
||||
func environmentEntries(base []string, overlay map[string]string, unset []string) []string {
|
||||
environment := make(map[string]string, len(base)+len(overlay))
|
||||
for _, entry := range base {
|
||||
key, value, ok := strings.Cut(entry, "=")
|
||||
if ok {
|
||||
environment[key] = value
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -79,6 +80,50 @@ func TestRunCanRemoveInheritedEnvironment(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunDirectoryEnvironmentPreservesExplicitPWDSelection(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("directory-derived PWD is a POSIX behavior")
|
||||
}
|
||||
parent := mustGetwd(t)
|
||||
t.Setenv("PWD", parent)
|
||||
workdir := t.TempDir()
|
||||
for _, test := range []struct {
|
||||
name, override, want string
|
||||
unset bool
|
||||
present bool
|
||||
}{
|
||||
{name: "directory", want: workdir, present: true},
|
||||
{name: "override", override: "selected PWD", want: "selected PWD", present: true},
|
||||
{name: "removed", unset: true},
|
||||
{name: "override after removal", unset: true, override: "selected PWD", want: "selected PWD", present: true},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
invocation := Invocation{
|
||||
Args: []string{helperExecutable(t), "-test.run=TestProcessHelper", "--", "pwd"},
|
||||
Dir: workdir,
|
||||
Env: map[string]string{"RELEASEKIT_PROCESS_HELPER": "1"},
|
||||
}
|
||||
if test.override != "" {
|
||||
invocation.Env["PWD"] = test.override
|
||||
}
|
||||
if test.unset {
|
||||
invocation.UnsetEnv = []string{"PWD"}
|
||||
}
|
||||
var stdout bytes.Buffer
|
||||
invocation.Stdout = &stdout
|
||||
if err := Run(t.Context(), invocation); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := stdout.String(), fmt.Sprintf("%s|%t", test.want, test.present); got != want {
|
||||
t.Fatalf("child PWD = %q, want %q", got, want)
|
||||
}
|
||||
if os.Getenv("PWD") != parent || mustGetwd(t) != parent {
|
||||
t.Fatal("child invocation changed the parent's directory or PWD")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunReportsMissingExecutable(t *testing.T) {
|
||||
err := Run(context.Background(), Invocation{Args: []string{"releasekit-command-that-does-not-exist"}})
|
||||
if err == nil || !strings.Contains(err.Error(), "releasekit-command-that-does-not-exist") {
|
||||
@@ -378,6 +423,10 @@ func TestProcessHelper(t *testing.T) {
|
||||
}
|
||||
mode := args[len(args)-1]
|
||||
switch mode {
|
||||
case "pwd":
|
||||
value, present := os.LookupEnv("PWD")
|
||||
fmt.Fprintf(os.Stdout, "%s|%t", value, present)
|
||||
os.Exit(0)
|
||||
case "success":
|
||||
workdir, err := os.Getwd()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user