Files
wehub-resource-sync 26f897c1ec
release / release-please (push) Failing after 1m49s
docs / build (push) Failing after 6m34s
release / build-and-upload (arm64, linux) (push) Has been cancelled
release / build-and-upload (arm64, windows) (push) Has been cancelled
release / build-darwin (amd64, darwin) (push) Has been cancelled
release / checksums (push) Has been cancelled
release / finalize (push) Has been cancelled
release / build-darwin (arm64, darwin) (push) Has been cancelled
release / build-and-upload (amd64, linux) (push) Has been cancelled
release / build-and-upload (amd64, windows) (push) Has been cancelled
docs / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:34:16 +08:00

123 lines
3.4 KiB
Go

package git
import (
"os"
"runtime"
"strings"
"testing"
)
// resolveEnv collapses a KEY=VALUE slice into a map using last-wins semantics,
// matching how exec resolves duplicate keys.
func resolveEnv(env []string) map[string]string {
m := make(map[string]string, len(env))
for _, kv := range env {
k, v, ok := strings.Cut(kv, "=")
if !ok {
continue
}
m[k] = v
}
return m
}
func TestNonInteractiveEnv_SetsGitOverrides(t *testing.T) {
got := resolveEnv(NonInteractiveEnv(""))
want := map[string]string{
"GIT_EDITOR": "true",
"GIT_SEQUENCE_EDITOR": "true",
"GIT_TERMINAL_PROMPT": "0",
}
for k, v := range want {
if got[k] != v {
t.Errorf("env %s = %q, want %q", k, got[k], v)
}
}
}
func TestNonInteractiveEnv_OverridesAmbientEditor(t *testing.T) {
t.Setenv("GIT_EDITOR", "vim")
t.Setenv("GIT_SEQUENCE_EDITOR", "nano")
t.Setenv("GIT_TERMINAL_PROMPT", "1")
got := resolveEnv(NonInteractiveEnv(""))
if got["GIT_EDITOR"] != "true" {
t.Errorf("GIT_EDITOR = %q, want \"true\" (ambient vim must be overridden)", got["GIT_EDITOR"])
}
if got["GIT_SEQUENCE_EDITOR"] != "true" {
t.Errorf("GIT_SEQUENCE_EDITOR = %q, want \"true\"", got["GIT_SEQUENCE_EDITOR"])
}
if got["GIT_TERMINAL_PROMPT"] != "0" {
t.Errorf("GIT_TERMINAL_PROMPT = %q, want \"0\"", got["GIT_TERMINAL_PROMPT"])
}
}
func TestNonInteractiveEnv_PreservesAmbientEnv(t *testing.T) {
t.Setenv("NM_ENV_PROBE_XYZ", "kept")
got := resolveEnv(NonInteractiveEnv(""))
if got["NM_ENV_PROBE_XYZ"] != "kept" {
t.Errorf("ambient env not preserved: NM_ENV_PROBE_XYZ = %q, want \"kept\"", got["NM_ENV_PROBE_XYZ"])
}
}
// TestNonInteractiveEnv_SetsPWDToDir locks in the PWD coupling. Assigning
// cmd.Env disables os/exec's automatic PWD=Cmd.Dir injection, so the helper
// must restore it; otherwise os.Getwd in the child resolves symlinks (e.g.
// /tmp -> /private/tmp on macOS) and reports a different working directory.
func TestNonInteractiveEnv_SetsPWDToDir(t *testing.T) {
t.Setenv("PWD", "/somewhere/else")
got := resolveEnv(NonInteractiveEnv("/work/dir"))
if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
if got["PWD"] != "/somewhere/else" {
t.Errorf("PWD = %q, want ambient PWD on %s", got["PWD"], runtime.GOOS)
}
return
}
if got["PWD"] != "/work/dir" {
t.Errorf("PWD = %q, want \"/work/dir\"", got["PWD"])
}
}
// TestNonInteractiveEnv_AbsolutizesRelativeDir locks in that a relative dir is
// absolutized before injection, matching os/exec (go.dev/issue/50599). POSIX
// defines PWD as an absolute pathname; a relative value like "." propagates
// through git receive-pack into hooks, where macOS /bin/sh (bash 3.2) trusts
// it and `pwd` collapses to "." (issue #269).
func TestNonInteractiveEnv_AbsolutizesRelativeDir(t *testing.T) {
t.Setenv("PWD", "/somewhere/else")
got := resolveEnv(NonInteractiveEnv("."))
if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
if got["PWD"] != "/somewhere/else" {
t.Errorf("PWD = %q, want ambient PWD on %s", got["PWD"], runtime.GOOS)
}
return
}
wd, err := os.Getwd()
if err != nil {
t.Fatalf("Getwd: %v", err)
}
if got["PWD"] != wd {
t.Errorf("PWD = %q, want absolute %q for relative dir \".\"", got["PWD"], wd)
}
}
func TestNonInteractiveEnv_EmptyDirLeavesAmbientPWD(t *testing.T) {
t.Setenv("PWD", "/ambient/pwd")
got := resolveEnv(NonInteractiveEnv(""))
if got["PWD"] != "/ambient/pwd" {
t.Errorf("PWD = %q, want ambient \"/ambient/pwd\" when dir is empty", got["PWD"])
}
}