11package gitops
22
33import (
4+ "fmt"
45 "strings"
56
67 "git-genius/internal/config"
@@ -66,13 +67,14 @@ func Status() bool {
6667}
6768
6869func Push (msg string ) bool {
69-
7070 if ! system .EnsureGitRepo () {
7171 return false
7272 }
7373
7474 ensureSafeDirectory ()
7575 cfg := config .Load ()
76+ stateBefore := InspectRepoState ()
77+ createdCommit := false
7678
7779 // ---------- FIRST COMMIT ----------
7880 if ! hasAnyCommit () {
@@ -95,10 +97,25 @@ func Push(msg string) bool {
9597 return false
9698 }
9799
100+ stagedNames , err := system .GitOutput ("diff" , "--cached" , "--name-only" )
101+ if err != nil {
102+ ui .Error ("Failed to inspect staged files" )
103+ return false
104+ }
105+ if stagedNames == "" {
106+ ui .Warn ("This repository has no files to commit yet" )
107+ ui .Info ("Create at least one file, then run Push changes again" )
108+ if cfg .Remote != "" {
109+ ui .Info ("Your remote can stay configured now; the first push just needs a real commit" )
110+ }
111+ return false
112+ }
113+
98114 if err := system .RunGit ("commit" , "-m" , msg ); err != nil {
99115 ui .Error ("Initial commit failed" )
100116 return false
101117 }
118+ createdCommit = true
102119 } else if isWorkingTreeDirty () {
103120 // ---------- NORMAL COMMIT ----------
104121 if msg == "" {
@@ -116,6 +133,7 @@ func Push(msg string) bool {
116133 ui .Error ("Commit failed" )
117134 return false
118135 }
136+ createdCommit = true
119137 } else {
120138 ui .Info ("No local file changes detected" )
121139 ui .Info ("Attempting to push any existing local commits" )
@@ -144,17 +162,22 @@ func Push(msg string) bool {
144162 return false
145163 }
146164
165+ if stateBefore .NeedsFirstPush || (! createdCommit && stateBefore .HasCommits && ! stateBefore .RemoteTrackingSeen ) {
166+ ui .Info ("This looks like the first push for " + cfg .Remote + "/" + branch )
167+ }
168+
147169 // ---------- PUSH ----------
148- if err := system .RunGitWithRemote (cfg .Remote , "push" , "-u" , cfg .Remote , branch ); err != nil {
170+ stderr , err := system .RunGitWithRemoteBuffered (cfg .Remote , "push" , "-u" , cfg .Remote , branch )
171+ if err != nil {
149172 ui .Error ("Push failed" )
150- if ! system .HasGitCredentialHelper () {
151- ui .Info ("Run Tools -> Git Auth / Credential Helper to reduce repeated HTTPS auth prompts" )
152- }
173+ printPushFailureSummary (cfg .Remote , branch , stderr )
153174 ui .Info ("Run Doctor if the problem persists" )
154175 return false
155176 }
156177
157- ui .Success ("Changes pushed successfully" )
178+ cfg .FirstPushDone = true
179+ config .Save (cfg )
180+ printPushSuccessSummary (cfg .Remote , branch , stateBefore , createdCommit )
158181 return true
159182}
160183
@@ -194,13 +217,17 @@ func Pull() bool {
194217 }
195218 }
196219
220+ stateBefore := InspectRepoState ()
221+ headBefore , _ := system .GitOutput ("rev-parse" , "HEAD" )
222+
197223 if err := system .RunGitWithRemote (cfg .Remote , "pull" , cfg .Remote , branch ); err != nil {
198224 ui .Error ("Pull failed" )
199225 ui .Info ("Try Smart Pull or run Doctor for more guidance" )
200226 return false
201227 }
202228
203- ui .Success ("Pull completed" )
229+ headAfter , _ := system .GitOutput ("rev-parse" , "HEAD" )
230+ printPullSuccessSummary (cfg .Remote , branch , stateBefore , headBefore != "" && headBefore != headAfter )
204231 return true
205232}
206233
@@ -226,3 +253,68 @@ func Fetch() bool {
226253 ui .Success ("Fetched all remotes" )
227254 return true
228255}
256+
257+ func printPushSuccessSummary (remote , branch string , before RepoState , createdCommit bool ) {
258+ after := InspectRepoState ()
259+
260+ ui .Header ("Push Summary" )
261+ ui .Success ("Remote : " + remote )
262+ ui .Success ("Branch : " + branch )
263+
264+ switch {
265+ case ! before .HasCommits && createdCommit :
266+ ui .Success ("Created the first commit and published the branch" )
267+ case before .NeedsFirstPush :
268+ ui .Success ("Published this branch to the remote for the first time" )
269+ case before .HasAheadBehind && before .Ahead > 0 :
270+ ui .Success (fmt .Sprintf ("Published %d local commit(s)" , before .Ahead ))
271+ case createdCommit :
272+ ui .Success ("Created a new commit and pushed it" )
273+ default :
274+ ui .Info ("Remote branch was already up to date before this push" )
275+ }
276+
277+ if after .HasAheadBehind {
278+ ui .Info ("Ahead/Behind : " + after .AheadBehindSummary ())
279+ }
280+ }
281+
282+ func printPushFailureSummary (remote , branch , stderr string ) {
283+ ui .Header ("Push Summary" )
284+ ui .Error ("Remote : " + remote )
285+ ui .Error ("Branch : " + branch )
286+
287+ if system .RemoteUsesHTTPS (remote ) {
288+ ui .Info ("HTTPS remote detected" )
289+ ui .Info ("Run Tools -> Git Auth / Credential Helper and preload the current GitHub token into Git" )
290+ ui .Info ("Check that the token still has repo access to this repository" )
291+ if ! system .HasGitCredentialHelper () {
292+ ui .Info ("No Git credential helper is configured yet" )
293+ }
294+ }
295+
296+ if strings .Contains (strings .ToLower (stderr ), "repository not found" ) {
297+ ui .Info ("Verify the remote URL and GitHub owner/repository in Setup or Create / Link GitHub Repository" )
298+ }
299+ }
300+
301+ func printPullSuccessSummary (remote , branch string , before RepoState , headChanged bool ) {
302+ after := InspectRepoState ()
303+
304+ ui .Header ("Pull Summary" )
305+ ui .Success ("Remote : " + remote )
306+ ui .Success ("Branch : " + branch )
307+
308+ switch {
309+ case before .HasAheadBehind && before .Behind > 0 :
310+ ui .Success (fmt .Sprintf ("Integrated %d remote commit(s)" , before .Behind ))
311+ case headChanged :
312+ ui .Success ("Local branch moved forward" )
313+ default :
314+ ui .Info ("Local branch was already up to date" )
315+ }
316+
317+ if after .HasAheadBehind {
318+ ui .Info ("Ahead/Behind : " + after .AheadBehindSummary ())
319+ }
320+ }
0 commit comments