@@ -2,158 +2,48 @@ package git
22
33import (
44 "fmt"
5- "os/exec"
65 "strings"
76
8- "github.com/git-rain/git-rain/internal/safety"
7+ harnessgit "github.com/git-fire/git-harness/git"
8+ harnessafety "github.com/git-fire/git-harness/safety"
99)
1010
11- // Worktree represents a git worktree
12- type Worktree struct {
13- Path string // Absolute path to worktree
14- Branch string // Current branch in this worktree
15- Head string // Current HEAD SHA
16- IsMain bool // True if this is the main worktree
17- }
11+ // Worktree is a git worktree (delegates to git-harness).
12+ type Worktree = harnessgit.Worktree
1813
19- // getCommitSHA returns the SHA of a commit ref
2014func getCommitSHA (repoPath , ref string ) (string , error ) {
21- cmd := exec .Command ("git" , "rev-parse" , ref )
22- cmd .Dir = repoPath
23-
24- output , err := cmd .Output ()
25- if err != nil {
26- return "" , fmt .Errorf ("git rev-parse failed for %s: %w" , ref , err )
27- }
28-
29- sha := strings .TrimSpace (string (output ))
30- return sha , nil
15+ return harnessgit .GetCommitSHA (repoPath , ref )
3116}
3217
3318// GetCommitSHA returns the SHA for a ref in the repository.
3419func GetCommitSHA (repoPath , ref string ) (string , error ) {
35- return getCommitSHA (repoPath , ref )
20+ return harnessgit . GetCommitSHA (repoPath , ref )
3621}
3722
38- // GetCurrentBranch returns the currently checked out branch
23+ // GetCurrentBranch returns the currently checked out branch.
3924func GetCurrentBranch (repoPath string ) (string , error ) {
40- cmd := exec .Command ("git" , "branch" , "--show-current" )
41- cmd .Dir = repoPath
42-
43- output , err := cmd .Output ()
44- if err != nil {
45- return "" , fmt .Errorf ("git branch --show-current failed: %w" , err )
46- }
47-
48- branch := strings .TrimSpace (string (output ))
49- if branch == "" {
50- return "" , fmt .Errorf ("not on any branch (detached HEAD?)" )
51- }
52-
53- return branch , nil
25+ return harnessgit .GetCurrentBranch (repoPath )
5426}
5527
56- // HasStagedChanges checks if there are staged changes
28+ // HasStagedChanges checks if there are staged changes.
5729func HasStagedChanges (repoPath string ) (bool , error ) {
58- cmd := exec .Command ("git" , "diff" , "--cached" , "--quiet" )
59- cmd .Dir = repoPath
60-
61- err := cmd .Run ()
62- if err != nil {
63- if exitErr , ok := err .(* exec.ExitError ); ok && exitErr .ExitCode () == 1 {
64- return true , nil
65- }
66- return false , fmt .Errorf ("git diff --cached --quiet failed: %w" , err )
67- }
68-
69- return false , nil
30+ return harnessgit .HasStagedChanges (repoPath )
7031}
7132
72- // HasUnstagedChanges checks if there are unstaged changes (including untracked files)
33+ // HasUnstagedChanges checks if there are unstaged changes (including untracked files).
7334func HasUnstagedChanges (repoPath string ) (bool , error ) {
74- cmd := exec .Command ("git" , "diff" , "--quiet" )
75- cmd .Dir = repoPath
76-
77- err := cmd .Run ()
78- hasModified := false
79- if err != nil {
80- if exitErr , ok := err .(* exec.ExitError ); ok && exitErr .ExitCode () == 1 {
81- hasModified = true
82- } else {
83- return false , fmt .Errorf ("git diff --quiet failed: %w" , err )
84- }
85- }
86-
87- cmd = exec .Command ("git" , "ls-files" , "--others" , "--exclude-standard" )
88- cmd .Dir = repoPath
89- output , err := cmd .Output ()
90- if err != nil {
91- return false , fmt .Errorf ("git ls-files failed: %w" , err )
92- }
93-
94- hasUntracked := len (strings .TrimSpace (string (output ))) > 0
95-
96- return hasModified || hasUntracked , nil
35+ return harnessgit .HasUnstagedChanges (repoPath )
9736}
9837
99- // ListWorktrees returns all worktrees for a repository
38+ // ListWorktrees returns all worktrees for a repository.
10039func ListWorktrees (repoPath string ) ([]Worktree , error ) {
101- cmd := exec .Command ("git" , "worktree" , "list" , "--porcelain" )
102- cmd .Dir = repoPath
103-
104- output , err := cmd .Output ()
105- if err != nil {
106- return nil , fmt .Errorf ("git worktree list failed: %w" , err )
107- }
108-
109- lines := strings .Split (string (output ), "\n " )
110- var worktrees []Worktree
111- var current Worktree
112- isFirst := true
113-
114- for _ , line := range lines {
115- line = strings .TrimSpace (line )
116- if line == "" {
117- if current .Path != "" {
118- current .IsMain = isFirst
119- worktrees = append (worktrees , current )
120- current = Worktree {}
121- isFirst = false
122- }
123- continue
124- }
125-
126- parts := strings .SplitN (line , " " , 2 )
127- if len (parts ) < 2 {
128- continue
129- }
130-
131- key := parts [0 ]
132- value := parts [1 ]
133-
134- switch key {
135- case "worktree" :
136- current .Path = value
137- case "HEAD" :
138- current .Head = value
139- case "branch" :
140- branch := strings .TrimPrefix (value , "refs/heads/" )
141- current .Branch = branch
142- }
143- }
144-
145- if current .Path != "" {
146- current .IsMain = isFirst
147- worktrees = append (worktrees , current )
148- }
149-
150- return worktrees , nil
40+ return harnessgit .ListWorktrees (repoPath )
15141}
15242
15343func commandError (action string , err error , output []byte ) error {
15444 out := strings .TrimSpace (string (output ))
15545 if out == "" {
15646 return fmt .Errorf ("%s failed: %w" , action , err )
15747 }
158- return fmt .Errorf ("%s failed: %w (stderr: %s)" , action , err , safety .SanitizeText (out ))
48+ return fmt .Errorf ("%s failed: %w (stderr: %s)" , action , err , harnessafety .SanitizeText (out ))
15949}
0 commit comments