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}