mirror of
https://github.com/marcusDenslow/FERRUM.git
synced 2026-10-25 20:28:51 +01:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
@@ -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.
Reference in New Issue
Block a user