|
9 | 9 | "net/http/httptest" |
10 | 10 | "net/url" |
11 | 11 | "os" |
| 12 | + "os/exec" |
12 | 13 | "path/filepath" |
13 | 14 | "runtime" |
14 | 15 | "strings" |
@@ -454,3 +455,116 @@ func TestInitNoDaemonWithAgentCreatesCommentedRepoConfig(t *testing.T) { |
454 | 455 | } |
455 | 456 | } |
456 | 457 | } |
| 458 | + |
| 459 | +func TestInstallHookFromLinkedWorktree(t *testing.T) { |
| 460 | + if runtime.GOOS == "windows" { |
| 461 | + t.Skip("test uses Unix worktree semantics") |
| 462 | + } |
| 463 | + |
| 464 | + // Set up a main repo with a relative core.hooksPath but |
| 465 | + // no hooks installed yet. |
| 466 | + repo := testutil.NewTestRepoWithCommit(t) |
| 467 | + customHooks := filepath.Join(repo.Root, ".githooks") |
| 468 | + require.NoError(t, os.MkdirAll(customHooks, 0755)) |
| 469 | + |
| 470 | + runGit := func(dir string, args ...string) string { |
| 471 | + t.Helper() |
| 472 | + cmd := exec.Command("git", args...) |
| 473 | + cmd.Dir = dir |
| 474 | + cmd.Env = append(os.Environ(), |
| 475 | + "GIT_AUTHOR_NAME=Test", |
| 476 | + "GIT_AUTHOR_EMAIL=test@test.com", |
| 477 | + "GIT_COMMITTER_NAME=Test", |
| 478 | + "GIT_COMMITTER_EMAIL=test@test.com", |
| 479 | + ) |
| 480 | + out, err := cmd.CombinedOutput() |
| 481 | + require.NoError(t, err, "git %v: %s", args, out) |
| 482 | + return strings.TrimSpace(string(out)) |
| 483 | + } |
| 484 | + |
| 485 | + runGit(repo.Root, "config", "core.hooksPath", ".githooks") |
| 486 | + |
| 487 | + // Create a linked worktree. |
| 488 | + wtDir := t.TempDir() |
| 489 | + resolved, err := filepath.EvalSymlinks(wtDir) |
| 490 | + require.NoError(t, err) |
| 491 | + runGit(repo.Root, "worktree", "add", resolved, "-b", "wt") |
| 492 | + |
| 493 | + // Run install-hook from the worktree. |
| 494 | + origDir, _ := os.Getwd() |
| 495 | + require.NoError(t, os.Chdir(resolved)) |
| 496 | + t.Cleanup(func() { os.Chdir(origDir) }) |
| 497 | + |
| 498 | + installCmd := installHookCmd() |
| 499 | + installCmd.SetArgs([]string{}) |
| 500 | + require.NoError(t, installCmd.Execute()) |
| 501 | + |
| 502 | + // The hooks should be installed in the main repo's .githooks. |
| 503 | + for _, name := range []string{"post-commit", "post-rewrite"} { |
| 504 | + _, err := os.Stat(filepath.Join(customHooks, name)) |
| 505 | + assert.NoError(t, err, |
| 506 | + "%s should exist in shared hooks dir", name) |
| 507 | + } |
| 508 | +} |
| 509 | + |
| 510 | +func TestUninstallHookFromLinkedWorktree(t *testing.T) { |
| 511 | + if runtime.GOOS == "windows" { |
| 512 | + t.Skip("test uses Unix worktree semantics") |
| 513 | + } |
| 514 | + |
| 515 | + // Set up a main repo with a relative core.hooksPath and |
| 516 | + // installed hooks. |
| 517 | + repo := testutil.NewTestRepoWithCommit(t) |
| 518 | + customHooks := filepath.Join(repo.Root, ".githooks") |
| 519 | + require.NoError(t, os.MkdirAll(customHooks, 0755)) |
| 520 | + |
| 521 | + runGit := func(dir string, args ...string) string { |
| 522 | + t.Helper() |
| 523 | + cmd := exec.Command("git", args...) |
| 524 | + cmd.Dir = dir |
| 525 | + cmd.Env = append(os.Environ(), |
| 526 | + "GIT_AUTHOR_NAME=Test", |
| 527 | + "GIT_AUTHOR_EMAIL=test@test.com", |
| 528 | + "GIT_COMMITTER_NAME=Test", |
| 529 | + "GIT_COMMITTER_EMAIL=test@test.com", |
| 530 | + ) |
| 531 | + out, err := cmd.CombinedOutput() |
| 532 | + require.NoError(t, err, "git %v: %s", args, out) |
| 533 | + return strings.TrimSpace(string(out)) |
| 534 | + } |
| 535 | + |
| 536 | + // Set relative core.hooksPath, install hooks. |
| 537 | + runGit(repo.Root, "config", "core.hooksPath", ".githooks") |
| 538 | + for _, name := range []string{"post-commit", "post-rewrite"} { |
| 539 | + var content string |
| 540 | + if name == "post-commit" { |
| 541 | + content = githook.GeneratePostCommit() |
| 542 | + } else { |
| 543 | + content = githook.GeneratePostRewrite() |
| 544 | + } |
| 545 | + require.NoError(t, os.WriteFile( |
| 546 | + filepath.Join(customHooks, name), |
| 547 | + []byte(content), 0755)) |
| 548 | + } |
| 549 | + |
| 550 | + // Create a linked worktree. |
| 551 | + wtDir := t.TempDir() |
| 552 | + resolved, err := filepath.EvalSymlinks(wtDir) |
| 553 | + require.NoError(t, err) |
| 554 | + runGit(repo.Root, "worktree", "add", resolved, "-b", "wt") |
| 555 | + |
| 556 | + // Run uninstall-hook from the worktree. |
| 557 | + origDir, _ := os.Getwd() |
| 558 | + require.NoError(t, os.Chdir(resolved)) |
| 559 | + t.Cleanup(func() { os.Chdir(origDir) }) |
| 560 | + |
| 561 | + cmd := uninstallHookCmd() |
| 562 | + require.NoError(t, cmd.Execute()) |
| 563 | + |
| 564 | + // The hooks in the main repo's .githooks should be removed. |
| 565 | + for _, name := range []string{"post-commit", "post-rewrite"} { |
| 566 | + _, err := os.Stat(filepath.Join(customHooks, name)) |
| 567 | + assert.ErrorIs(t, err, fs.ErrNotExist, |
| 568 | + "%s should be removed from shared hooks dir", name) |
| 569 | + } |
| 570 | +} |
0 commit comments