Skip to content
6 changes: 4 additions & 2 deletions cmd/entire/cli/trail_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2412,11 +2412,13 @@ func fetchBranchFromRemote(ctx context.Context, remote, branchName string) error
}

// pushBranchToRemote pushes a branch to remote, which callers resolve through
// resolveTrailPushRemote rather than assuming "origin".
// resolveTrailPushRemote rather than assuming "origin". This must run Git's
// pre-push hooks: Entire's hook publishes any checkpoint data that was captured
// before the trail branch was created.
func pushBranchToRemote(ctx context.Context, remote, branchName string) error {
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel()
cmd := exec.CommandContext(ctx, "git", "push", "--no-verify", "-u", remote, branchName)
cmd := exec.CommandContext(ctx, "git", "push", "-u", remote, branchName)
if output, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("%s: %w", strings.TrimSpace(string(output)), err)
}
Expand Down
26 changes: 26 additions & 0 deletions cmd/entire/cli/trail_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2764,6 +2764,32 @@ func TestResolveTrailPushRemote(t *testing.T) {
}
}

// TestPrepareTrailCreateBranchRunsPrePushHook guards checkpoint publication:
// trail creation must push like a user would, without bypassing Entire's hook.
func TestPrepareTrailCreateBranchRunsPrePushHook(t *testing.T) {
localDir, originDir, repo := initTrailCleanupRepo(t)
defer repo.Close()
t.Chdir(localDir)

hooksDir := filepath.Join(localDir, ".git", "hooks")
require.NoError(t, os.MkdirAll(hooksDir, 0o755))
require.NoError(t, os.WriteFile(
filepath.Join(hooksDir, "pre-push"),
[]byte("#!/bin/sh\nprintf '%s\\n' \"$1\" > \"$(git rev-parse --git-dir)/trail-create-pre-push-ran\"\n"),
0o755,
))

const branch = "feature/checkpoint-sync"
var out, errOut bytes.Buffer
_, err := prepareTrailCreateBranch(context.Background(), &out, &errOut, repo, "origin", branch, "main", false)

require.NoError(t, err, "stderr: %s", errOut.String())
require.True(t, gitBranchExistsTrailTest(t, originDir, branch), "branch missing from remote")
hookRemote, err := os.ReadFile(filepath.Join(localDir, ".git", "trail-create-pre-push-ran"))
require.NoError(t, err, "trail create branch push bypassed the pre-push hook")
require.Equal(t, "origin\n", string(hookRemote))
}

// TestPrepareTrailCreateBranchPushesToDeclaredRemote is the end-to-end shape of
// the bug: origin exists and is a perfectly good remote, but the branch's
// declared push destination is a different one. The branch must arrive there and
Expand Down
1 change: 1 addition & 0 deletions internal/entireclient/contexts/contexts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func TestLoad_MissingFileReturnsEmpty(t *testing.T) {
}
if f == nil {
t.Fatal("Load returned nil File")
return
}
if f.CurrentContext != "" || len(f.Contexts) != 0 {
t.Errorf("expected zero-valued File, got %+v", f)
Expand Down
Loading