added handling for devergance

when renaming a commit the program was unable to Push because the local branch had diverged from the remote branch. now there is a divergance handler that asks you if you want to force push anyway, which is very nice!
This commit is contained in:
2025-06-06 21:22:37 +02:00
parent ae306fee97
commit 3f9c126b9b
6 changed files with 152 additions and 1 deletions

View File

@@ -248,3 +248,57 @@ int get_repo_url(char *url, size_t url_size) {
return 0;
}
/**
* Check if the current branch has diverged from its remote tracking branch
*/
int check_branch_divergence(int *commits_ahead, int *commits_behind) {
if (!commits_ahead || !commits_behind) {
return 0;
}
*commits_ahead = 0;
*commits_behind = 0;
// Check if we have a remote tracking branch
FILE *fp = popen("git rev-parse --abbrev-ref @{u} 2>/dev/null", "r");
if (!fp) {
return 0;
}
char remote_branch[256];
if (fgets(remote_branch, sizeof(remote_branch), fp) == NULL) {
pclose(fp);
return 0; // No remote tracking branch
}
pclose(fp);
// Remove newline
char *newline = strchr(remote_branch, '\n');
if (newline) {
*newline = '\0';
}
// Get commits ahead (local commits not in remote)
fp = popen("git rev-list --count @{u}..HEAD 2>/dev/null", "r");
if (fp) {
char count_str[32];
if (fgets(count_str, sizeof(count_str), fp) != NULL) {
*commits_ahead = atoi(count_str);
}
pclose(fp);
}
// Get commits behind (remote commits not in local)
fp = popen("git rev-list --count HEAD..@{u} 2>/dev/null", "r");
if (fp) {
char count_str[32];
if (fgets(count_str, sizeof(count_str), fp) != NULL) {
*commits_behind = atoi(count_str);
}
pclose(fp);
}
// Branch has diverged if we have commits both ahead and behind
return (*commits_ahead > 0 && *commits_behind > 0) ? 1 : 0;
}

View File

@@ -47,4 +47,13 @@ int get_git_repo_name(char *repo_name, size_t buffer_size);
*/
char *get_git_status(void);
/**
* Check if the current branch has diverged from its remote tracking branch
*
* @param commits_ahead Pointer to store number of commits ahead of remote
* @param commits_behind Pointer to store number of commits behind remote
* @return 1 if diverged (both ahead and behind > 0), 0 otherwise
*/
int check_branch_divergence(int *commits_ahead, int *commits_behind);
#endif // GIT_INTEGRATION_H

Binary file not shown.

View File

@@ -4,6 +4,7 @@
*/
#include "ncurses_diff_viewer.h"
#include "git_integration.h"
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
@@ -488,6 +489,73 @@ void mark_all_files(NCursesDiffViewer *viewer) {
}
}
/**
* Show confirmation dialog for diverged branch
* Returns 1 for force push, 0 for cancel
*/
int show_diverged_branch_dialog(int commits_ahead, int commits_behind) {
// Save current screen
WINDOW *saved_screen = dupwin(stdscr);
// Calculate window dimensions
int dialog_width = 60;
int dialog_height = 8;
int start_x = COLS / 2 - dialog_width / 2;
int start_y = LINES / 2 - dialog_height / 2;
// Create dialog window
WINDOW *dialog_win = newwin(dialog_height, dialog_width, start_y, start_x);
if (!dialog_win) {
if (saved_screen)
delwin(saved_screen);
return 0;
}
// Draw dialog
wattron(dialog_win, COLOR_PAIR(3)); // Red for warning
box(dialog_win, 0, 0);
// Title
mvwprintw(dialog_win, 1, 2, "Branch has diverged!");
// Message
mvwprintw(dialog_win, 3, 2, "Local: %d commit(s) ahead", commits_ahead);
mvwprintw(dialog_win, 4, 2, "Remote: %d commit(s) ahead", commits_behind);
// Instructions
mvwprintw(dialog_win, 6, 2, "Force push anyway? (y/N):");
wattroff(dialog_win, COLOR_PAIR(3));
wrefresh(dialog_win);
// Get user input
int ch;
int result = 0;
while ((ch = wgetch(dialog_win)) != ERR) {
if (ch == 'y' || ch == 'Y') {
result = 1;
break;
} else if (ch == 'n' || ch == 'N' || ch == 27 || ch == 'q') { // ESC or q or n
result = 0;
break;
} else if (ch == '\n' || ch == '\r') {
result = 0; // Default to no on Enter
break;
}
}
// Cleanup
delwin(dialog_win);
if (saved_screen) {
touchwin(saved_screen);
wrefresh(saved_screen);
delwin(saved_screen);
}
return result;
}
/**
* Get commit title and message input from user
*/
@@ -1024,6 +1092,19 @@ int push_commit(NCursesDiffViewer *viewer, int commit_index) {
if (!viewer || commit_index < 0 || commit_index >= viewer->commit_count)
return 0;
// Check for branch divergence first
int commits_ahead = 0;
int commits_behind = 0;
int is_diverged = check_branch_divergence(&commits_ahead, &commits_behind);
// If diverged, show confirmation dialog
if (is_diverged) {
if (!show_diverged_branch_dialog(commits_ahead, commits_behind)) {
// User cancelled
return 0;
}
}
// Start pushing animation immediately
viewer->sync_status = SYNC_STATUS_PUSHING_APPEARING;
viewer->animation_frame = 0;
@@ -1033,7 +1114,14 @@ int push_commit(NCursesDiffViewer *viewer, int commit_index) {
render_status_bar(viewer);
// Do the actual push work
int result = system("git push origin 2>/dev/null >/dev/null");
int result;
if (is_diverged) {
// Use force push with lease for safety
result = system("git push --force-with-lease origin 2>/dev/null >/dev/null");
} else {
// Normal push
result = system("git push origin 2>/dev/null >/dev/null");
}
if (result == 0) {
// Refresh commit history to get proper push status

Binary file not shown.

BIN
shell

Binary file not shown.