-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgit.go
184 lines (157 loc) · 5.14 KB
/
git.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package plasmactlmeta
import (
"bytes"
"fmt"
"log"
"os"
"os/exec"
"strings"
"time"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/launchrctl/launchr"
)
// Checks for uncommitted changes and creates a commit if any are found
func commitChangesIfAny() error {
// Open the existing repository
repoPath, err := os.Getwd()
if err != nil {
log.Fatalf("failed to get current directory: %v", err)
}
repo, err := git.PlainOpen(repoPath)
if err != nil {
return fmt.Errorf("failed to open repository: %w", err)
}
// Get the working tree
worktree, err := repo.Worktree()
if err != nil {
return fmt.Errorf("failed to get worktree: %w", err)
}
// Check for uncommitted changes
status, err := worktree.Status()
if err != nil {
return fmt.Errorf("failed to get worktree status: %w", err)
}
if status.IsClean() {
launchr.Log().Debug("No changes to commit.")
return nil
}
launchr.Term().Info().Println("Unversioned changes detected. Creating commit...")
// Add all changes to the index
err = worktree.AddGlob(".")
if err != nil {
return fmt.Errorf("failed to stage changes: %w", err)
}
// Create a commit with the staged changes
commitMessage := "Work in progress"
commit, err := worktree.Commit(commitMessage, &git.CommitOptions{
Author: &object.Signature{
Name: "Plasmactl",
Email: "[email protected]",
When: time.Now(),
},
})
if err != nil {
return fmt.Errorf("failed to commit changes: %w", err)
}
// Print commit details
obj, err := repo.CommitObject(commit)
if err != nil {
return fmt.Errorf("failed to retrieve commit object: %w", err)
}
//fmt.Printf("Created %s\n", obj.String())
launchr.Term().Printf("Created commit %s\n", obj.Hash.String())
launchr.Term().Printf("Author: %s <%s>\n", obj.Author.Name, obj.Author.Email)
launchr.Term().Printf("Date: %s\n", obj.Author.When.Format("Mon Jan 2 15:04:05 2006 -0700"))
launchr.Term().Printf("Message: %s\n", obj.Message)
launchr.Term().Printf("\n")
return nil
}
// Checks for unpushed commits and pushes them if any are found
func pushCommitsIfAny() error {
// Check for un-pushed commits
cmdFetch := exec.Command("git", "fetch", "--quiet")
if err := cmdFetch.Run(); err != nil {
return fmt.Errorf("failed to fetch updates: %w", err)
}
cmdStatus := exec.Command("git", "status", "-sb")
var statusOut bytes.Buffer
cmdStatus.Stdout = &statusOut
if err := cmdStatus.Run(); err != nil {
return fmt.Errorf("failed to get git status: %w", err)
}
// Parse status output
status := statusOut.String()
if strings.Contains(status, "[ahead") {
launchr.Term().Info().Println("There are un-pushed commits: Pushing...")
// Push the commits
cmdPush := exec.Command("git", "push")
cmdPush.Stdout = &statusOut
cmdPush.Stderr = &statusOut
if err := cmdPush.Run(); err != nil {
return fmt.Errorf("failed to push commits: %w", err)
}
launchr.Term().Info().Println("Successfully pushed commits.")
launchr.Term().Printf("\n")
} else {
launchr.Log().Debug("No un-pushed commits found.")
}
return nil
}
func pushBranchIfNotRemote() error {
// Verify the remote name
cmdRemote := exec.Command("git", "remote")
var remoteOut bytes.Buffer
cmdRemote.Stdout = &remoteOut
if err := cmdRemote.Run(); err != nil {
return fmt.Errorf("failed to list remotes: %w", err)
}
// Ensure "origin" exists in the list of remotes
remoteList := strings.Split(strings.TrimSpace(remoteOut.String()), "\n")
hasOrigin := false
for _, remote := range remoteList {
if strings.TrimSpace(remote) == "origin" {
hasOrigin = true
break
}
}
if !hasOrigin {
return fmt.Errorf("git remote server 'origin' not found; please ensure a remote server named 'origin' exists")
}
// Fetch updates to ensure we have the latest remote information
cmdFetch := exec.Command("git", "fetch", "--quiet", "origin")
if err := cmdFetch.Run(); err != nil {
return fmt.Errorf("failed to fetch updates: %w", err)
}
// Get the current git status with tracking information
cmdStatus := exec.Command("git", "status", "-sb")
var statusOut bytes.Buffer
cmdStatus.Stdout = &statusOut
if err := cmdStatus.Run(); err != nil {
return fmt.Errorf("failed to get git status: %w", err)
}
// Parse the output of `git status -sb`
status := strings.TrimSpace(statusOut.String())
if !strings.HasPrefix(status, "##") {
return fmt.Errorf("unexpected git status output: %s", status)
}
// Extract branch info
statusLine := strings.TrimPrefix(status, "## ")
parts := strings.Split(statusLine, "...")
branchName := parts[0]
if len(parts) == 1 {
// No remote tracking information means the branch is local-only
launchr.Term().Info().Printf("Branch '%s' exists locally but not remotely: Pushing...\n", branchName)
// Push the branch to the remote
cmdPush := exec.Command("git", "push", "--set-upstream", "origin", branchName)
cmdPush.Stdout = &statusOut
cmdPush.Stderr = &statusOut
if err := cmdPush.Run(); err != nil {
return fmt.Errorf("failed to push branch '%s': %w", branchName, err)
}
launchr.Term().Info().Println("Successfully pushed branch")
} else {
launchr.Log().Debug("Branch '%s' already exists remotely", "branch", branchName)
}
return nil
}