From 0ad3dae502e92dc5fb7f46676b3b689d020d9557 Mon Sep 17 00:00:00 2001 From: Thales Maciel Date: Sun, 22 Mar 2026 00:58:51 -0300 Subject: [PATCH] Fix vm run guest checkout ownership Extract the host worktree overlay with tar -o so the guest repo stays owned by root instead of inheriting host UID/GID metadata. That avoids Git's dubious ownership check on /root/ after vm run.\n\nAlso register the guest checkout as a safe.directory during repo setup so opencode and manual git commands can read branch state reliably after attach.\n\nValidation: GOCACHE=/tmp/banger-gocache go test ./... and make build. --- internal/cli/banger.go | 3 ++- internal/cli/cli_test.go | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/internal/cli/banger.go b/internal/cli/banger.go index cb595b6..56e850d 100644 --- a/internal/cli/banger.go +++ b/internal/cli/banger.go @@ -1589,7 +1589,7 @@ func importVMRunRepoToGuest(ctx context.Context, client vmRunGuestClient, spec v return formatVMRunStepError("prepare guest checkout", err, scriptLog.String()) } var overlayLog bytes.Buffer - remoteCommand := fmt.Sprintf("tar -C %s --strip-components=1 -xf -", shellQuote(vmRunGuestDir(spec.RepoName))) + remoteCommand := fmt.Sprintf("tar -o -C %s --strip-components=1 -xf -", shellQuote(vmRunGuestDir(spec.RepoName))) if err := client.StreamTarEntries(ctx, spec.RepoRoot, spec.OverlayPaths, remoteCommand, &overlayLog); err != nil { return formatVMRunStepError("overlay host working tree", err, overlayLog.String()) } @@ -1640,6 +1640,7 @@ func vmRunCloneScript(spec vmRunRepoSpec) string { fmt.Fprintf(&script, "git -C \"$DIR\" checkout --detach %s\n", shellQuote(spec.HeadCommit)) } script.WriteString("find \"$DIR\" -mindepth 1 -maxdepth 1 ! -name .git -exec rm -rf {} +\n") + script.WriteString("git config --global --add safe.directory \"$DIR\"\n") return script.String() } diff --git a/internal/cli/cli_test.go b/internal/cli/cli_test.go index 5083811..95e77ad 100644 --- a/internal/cli/cli_test.go +++ b/internal/cli/cli_test.go @@ -1121,13 +1121,16 @@ func TestRunVMRunCreatesImportsAndAttaches(t *testing.T) { if !strings.Contains(fakeClient.script, `git -C "$DIR" checkout -B 'feature' 'cafebabe'`) { t.Fatalf("script = %q, want guest branch checkout", fakeClient.script) } + if !strings.Contains(fakeClient.script, `git config --global --add safe.directory "$DIR"`) { + t.Fatalf("script = %q, want guest safe.directory config", fakeClient.script) + } if fakeClient.streamSourceDir != repoRoot { t.Fatalf("streamSourceDir = %q, want %q", fakeClient.streamSourceDir, repoRoot) } if !reflect.DeepEqual(fakeClient.streamEntries, spec.OverlayPaths) { t.Fatalf("streamEntries = %v, want %v", fakeClient.streamEntries, spec.OverlayPaths) } - if fakeClient.streamCommand != "tar -C '/root/repo' --strip-components=1 -xf -" { + if fakeClient.streamCommand != "tar -o -C '/root/repo' --strip-components=1 -xf -" { t.Fatalf("streamCommand = %q", fakeClient.streamCommand) } wantAttach := []string{"attach", "--dir", "/root/repo", "http://172.16.0.2:4096"}