Worktree checkout rejects Windows reserved device names (e.g. prn.sh) on Linux/macOS — regression since v5.19.1
Worktree.Checkout (and therefore PlainClone) refuses to check out a file whose base name matches a Windows reserved device name (CON, PRN, AUX, NUL, COM1-9, LPT1-9), even on Linux/macOS where such names are valid. Real git has no such restriction on non-Windows platforms.
Regression: working in v5.19.0, broken in v5.19.1, still broken in v5.19.2 and main (at time of writing, b15e610f).
package main
import (
"os"
"os/exec"
git "github.com/go-git/go-git/v5"
)
func run(dir string, args ...string) {
cmd := exec.Command("git", args...)
cmd.Dir = dir
cmd.Env = append(os.Environ(), "GIT_AUTHOR_NAME=t", "[email protected]",
"GIT_COMMITTER_NAME=t", "[email protected]")
if out, err := cmd.CombinedOutput(); err != nil {
panic(string(out))
}
}
func main() {
src, _ := os.MkdirTemp("", "src")
run(src, "init", "-q", "-b", "master")
os.WriteFile(src+"/prn.sh", []byte("echo hi\n"), 0644)
run(src, "add", "-A")
run(src, "commit", "-q", "-m", "add prn.sh")
_, err := git.PlainClone(os.TempDir()+"/dst", false, &git.CloneOptions{URL: src})
if err != nil {
panic(err) // invalid path: "prn.sh"
}
}Expected: clone succeeds — matches real git's behavior on Linux/macOS.
Actual: lstat: invalid path: "prn.sh" (or openfile: invalid path: ...).
Cause: worktreeFilesystem.validPath (worktree_fs.go) calls pathutil.WindowsValidPath, which rejects reserved device names unconditionally regardless of OS, gated only by core.protectNTFS — and defaultProtectNTFS() now hardcodes true on every platform. Real git's equivalent check (is_valid_win32_path) is compile-time restricted to Windows-native/Cygwin builds.
You already fixed this exact class of bug once: pathutil.ValidTreePath (the tree-read path) had the same unconditional reserved-name check and was scoped to Windows/Cygwin-only in ce4cca1861 ("align tree-path validation with upstream Git"). worktreeFilesystem.validPath — the checkout/write path — needs the same fix; it was missed.
Source: go-git/go-git