Merge pull request 'forgekey: a command starts in a directory that exists (issue 734)' (#93) from fix/daemon-dir-kept into main
This commit was merged in pull request #93.
This commit is contained in:
+26
-1
@@ -43,7 +43,8 @@ func ExecRunnerFor(bound time.Duration) Runner {
|
||||
|
||||
// ExecRunnerClean is ExecRunnerFor whose commands get exactly the env argument as their environment, and nothing of
|
||||
// this process's (issue 1497; novox/hq ADR 0466 §4: no registry password in a fetch's environment). The caller
|
||||
// gives PATH and HOME itself. A directory is the command's own business (`git -C`, `go -C`).
|
||||
// gives PATH and HOME itself. A directory is the command's own business (`git -C`, `go -C`): it is started in the HOME
|
||||
// it is given, or the machine's temporary directory, never in this process's (stableDir).
|
||||
func ExecRunnerClean(bound time.Duration) Runner {
|
||||
return func(ctx context.Context, env []string, name string, args ...string) Ran {
|
||||
return execRun(ctx, bound, true, env, name, args...)
|
||||
@@ -62,6 +63,7 @@ func execRun(ctx context.Context, bound time.Duration, clean bool, env []string,
|
||||
} else {
|
||||
cmd.Env = append(os.Environ(), env...)
|
||||
}
|
||||
cmd.Dir = stableDir(clean, env)
|
||||
var out, errb bytes.Buffer
|
||||
cmd.Stdout, cmd.Stderr = &out, &errb
|
||||
err := cmd.Run()
|
||||
@@ -83,6 +85,29 @@ func execRun(ctx context.Context, bound time.Duration, clean bool, env []string,
|
||||
return r
|
||||
}
|
||||
|
||||
// stableDir is the directory a command starts in when it names none (novox/hq issue 734). **Never one that may be
|
||||
// deleted under it**: a module runs in the directory its build was unpacked in, which a new build replaces, and a
|
||||
// command started there inherits it — `go version` then fails "getwd: no such file or directory" before it reads
|
||||
// anything. A clean command starts in the HOME it is given, or the temporary directory; any other keeps this
|
||||
// process's directory while it exists, and starts in the temporary directory once it is gone. "" is this process's.
|
||||
func stableDir(clean bool, env []string) string {
|
||||
if !clean {
|
||||
if _, err := os.Getwd(); err == nil {
|
||||
return ""
|
||||
}
|
||||
return os.TempDir()
|
||||
}
|
||||
for i := len(env) - 1; i >= 0; i-- {
|
||||
if home, ok := strings.CutPrefix(env[i], "HOME="); ok {
|
||||
if info, err := os.Stat(home); err == nil && info.IsDir() {
|
||||
return home
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return os.TempDir()
|
||||
}
|
||||
|
||||
func firstLine(s string) string {
|
||||
for _, l := range strings.Split(s, "\n") {
|
||||
if l = strings.TrimSpace(l); l != "" {
|
||||
|
||||
@@ -48,13 +48,29 @@ func TestExecRunnerForZeroIsCutByItsContext(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// 1497/AC4: ExecRunnerClean(0) runs env with only the given words: PATH and HOME, not the process's secret.
|
||||
// 1497/AC4: ExecRunnerClean(0) runs env with only the given words: PATH and HOME, not the process's secret. And issue
|
||||
// 734: run from a process whose own directory was deleted under it (a module whose build a new one replaced), a clean
|
||||
// command starts in its HOME, and any other in the temporary directory, rather than failing to find where it is.
|
||||
func TestExecRunnerCleanGivesTheCommandOnlyTheEnvArgument(t *testing.T) {
|
||||
t.Setenv("MESH_TEST_SECRET", "x")
|
||||
r := ExecRunnerClean(0)(context.Background(), []string{"PATH=" + os.Getenv("PATH"), "HOME=/h"}, "env")
|
||||
if r.Status != 0 || !strings.Contains(r.Stdout, "HOME=/h") || !strings.Contains(r.Stdout, "PATH=") || strings.Contains(r.Stdout, "MESH_TEST_SECRET") {
|
||||
t.Errorf("ran = %+v", r)
|
||||
}
|
||||
|
||||
home, gone := t.TempDir(), t.TempDir()
|
||||
t.Chdir(gone)
|
||||
if err := os.Remove(gone); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r = ExecRunnerClean(0)(context.Background(), []string{"PATH=" + os.Getenv("PATH"), "HOME=" + home}, "pwd")
|
||||
if r.Status != 0 || strings.TrimSpace(r.Stdout) != home {
|
||||
t.Errorf("a clean command run from a deleted directory = %+v, want it started in its HOME %s", r, home)
|
||||
}
|
||||
r = ExecRunnerFor(0)(context.Background(), nil, "pwd")
|
||||
if r.Status != 0 || strings.TrimSpace(r.Stdout) != os.TempDir() {
|
||||
t.Errorf("a command run from a deleted directory = %+v, want it started in %s", r, os.TempDir())
|
||||
}
|
||||
}
|
||||
|
||||
// 1497/AC5: ExecRunnerFor(0) is unchanged: the env argument is added to the process's environment.
|
||||
|
||||
Reference in New Issue
Block a user