hooks.go
1package pgit
2
3import (
4 "fmt"
5 "os"
6 "path/filepath"
7 "strings"
8)
9
10func InstallHook(repoPath string) error {
11 absRepoPath, err := filepath.Abs(repoPath)
12 if err != nil {
13 return fmt.Errorf("could not resolve repo path: %w", err)
14 }
15
16 hookContent, err := EmbedFS.ReadFile("hooks/post-commit.bash")
17 if err != nil {
18 return fmt.Errorf("could not read embedded hook: %w", err)
19 }
20
21 hooksDir := filepath.Join(absRepoPath, ".git", "hooks")
22 if _, err := os.Stat(hooksDir); os.IsNotExist(err) {
23 bareHooksDir := filepath.Join(repoPath, "hooks")
24 if _, err := os.Stat(bareHooksDir); err == nil {
25 hooksDir = bareHooksDir
26 fmt.Printf("Detected bare repository, installing to %s\n", hooksDir)
27 }
28 }
29
30 postCommitHook := filepath.Join(hooksDir, "post-commit")
31
32 if err := os.MkdirAll(hooksDir, 0755); err != nil {
33 return fmt.Errorf("could not create hooks directory: %w", err)
34 }
35
36 if _, err := os.Stat(postCommitHook); err == nil {
37 backupPath := postCommitHook + ".backup"
38 if err := os.Rename(postCommitHook, backupPath); err != nil {
39 return fmt.Errorf("failed to backup existing hook: %w", err)
40 }
41 fmt.Printf("Backed up existing post-commit hook to %s\n", backupPath)
42 }
43
44 if err := os.WriteFile(postCommitHook, hookContent, 0755); err != nil {
45 return fmt.Errorf("failed to write hook: %w", err)
46 }
47
48 fmt.Printf("Installed post-commit hook to %s\n", postCommitHook)
49 fmt.Println("Commits with issue references (e.g., 'fixes #872a52d') will now automatically close issues")
50 return nil
51}
52
53func UninstallHook(repoPath string) error {
54 absRepoPath, err := filepath.Abs(repoPath)
55 if err != nil {
56 return fmt.Errorf("could not resolve repo path: %w", err)
57 }
58
59 hooksDir := filepath.Join(absRepoPath, ".git", "hooks")
60 if _, err := os.Stat(hooksDir); os.IsNotExist(err) {
61 bareHooksDir := filepath.Join(repoPath, "hooks")
62 if _, err := os.Stat(bareHooksDir); err == nil {
63 hooksDir = bareHooksDir
64 }
65 }
66
67 postCommitHook := filepath.Join(hooksDir, "post-commit")
68
69 data, err := os.ReadFile(postCommitHook)
70 if err != nil {
71 if os.IsNotExist(err) {
72 fmt.Println("No post-commit hook found")
73 return nil
74 }
75 return fmt.Errorf("failed to read hook: %w", err)
76 }
77
78 if !strings.Contains(string(data), "pgit post-commit hook") {
79 return fmt.Errorf("post-commit hook is not a pgit hook (not removing)")
80 }
81
82 if err := os.Remove(postCommitHook); err != nil {
83 return fmt.Errorf("failed to remove hook: %w", err)
84 }
85
86 backupPath := postCommitHook + ".backup"
87 if _, err := os.Stat(backupPath); err == nil {
88 if err := os.Rename(backupPath, postCommitHook); err != nil {
89 return fmt.Errorf("failed to restore backup: %w", err)
90 }
91 fmt.Printf("Restored backup hook from %s\n", backupPath)
92 }
93
94 fmt.Println("Uninstalled pgit post-commit hook")
95 return nil
96}