Ticket #2863 (mcdiff bidirectional merge enhancement)

Added feature for the mcdiff for the bidirectional merge.
    With F15 mcdiffviewer merge left panel to right panel direction.

    original patch by Gergely Szasz <szaszg@hu.inter.net>

Signed-off-by: Ilia Maslakov <il.smind@gmail.com>

added bind "MergeOther" into mc.keymap.default, mc.keymap.emacs.

Signed-off-by: Ilia Maslakov <il.smind@gmail.com>
This commit is contained in:
Gergely Szasz 2012-08-24 18:30:12 +04:00 committed by Ilia Maslakov
parent 961019d078
commit d8aa98b7d4
7 changed files with 94 additions and 34 deletions

View File

@ -353,6 +353,7 @@ static name_keymap_t command_names[] = {
{"HunkPrev", CK_HunkPrev}, {"HunkPrev", CK_HunkPrev},
{"EditOther", CK_EditOther}, {"EditOther", CK_EditOther},
{"Merge", CK_Merge}, {"Merge", CK_Merge},
{"MergeOther", CK_MergeOther},
#endif /* USE_DIFF_VIEW */ #endif /* USE_DIFF_VIEW */
{NULL, CK_IgnoreKey} {NULL, CK_IgnoreKey}

View File

@ -328,7 +328,8 @@ enum
CK_HunkNext, CK_HunkNext,
CK_HunkPrev, CK_HunkPrev,
CK_EditOther, CK_EditOther,
CK_Merge CK_Merge,
CK_MergeOther
}; };
/*** structures declarations (and typedefs of structures)*****************************************/ /*** structures declarations (and typedefs of structures)*****************************************/

View File

@ -432,6 +432,7 @@ Save = f2
Edit = f4 Edit = f4
EditOther = f14 EditOther = f14
Merge = f5 Merge = f5
MergeOther = f15
Search = f7 Search = f7
SearchContinue = f17 SearchContinue = f17
Options = f9 Options = f9

View File

@ -434,6 +434,7 @@ Save = f2
Edit = f4 Edit = f4
EditOther = f14 EditOther = f14
Merge = f5 Merge = f5
MergeOther = f15
Search = f7 Search = f7
SearchContinue = f17 SearchContinue = f17
Options = f9 Options = f9

View File

@ -84,7 +84,7 @@ typedef struct WDiff
char *label[2]; char *label[2];
FBUF *f[2]; FBUF *f[2];
const char *backup_sufix; const char *backup_sufix;
gboolean merged; gboolean merged[2];
GArray *a[2]; GArray *a[2];
GPtrArray *hdiff; GPtrArray *hdiff;
int ndiff; /* number of hunks */ int ndiff; /* number of hunks */

View File

@ -2061,12 +2061,17 @@ get_current_hunk (WDiff * dview, int *start_line1, int *end_line1, int *start_li
} }
static void static void
dview_remove_hunk (WDiff * dview, FILE * merge_file, int from1, int to1) dview_remove_hunk (WDiff * dview, FILE * merge_file, int from1, int to1, gboolean merge_direction)
{ {
int line; int line;
char buf[BUF_10K]; char buf[BUF_10K];
FILE *f0; FILE *f0;
if (merge_direction)
f0 = fopen (dview->file[1], "r");
else
f0 = fopen (dview->file[0], "r"); f0 = fopen (dview->file[0], "r");
line = 0; line = 0;
while (fgets (buf, sizeof (buf), f0) != NULL && line < from1 - 1) while (fgets (buf, sizeof (buf), f0) != NULL && line < from1 - 1)
{ {
@ -2083,14 +2088,25 @@ dview_remove_hunk (WDiff * dview, FILE * merge_file, int from1, int to1)
} }
static void static void
dview_add_hunk (WDiff * dview, FILE * merge_file, int from1, int from2, int to2) dview_add_hunk (WDiff * dview, FILE * merge_file, int from1, int from2, int to2,
gboolean merge_direction)
{ {
int line; int line;
char buf[BUF_10K]; char buf[BUF_10K];
FILE *f0; FILE *f0;
FILE *f1; FILE *f1;
if (merge_direction)
{
f0 = fopen (dview->file[1], "r");
f1 = fopen (dview->file[0], "r");
}
else
{
f0 = fopen (dview->file[0], "r"); f0 = fopen (dview->file[0], "r");
f1 = fopen (dview->file[1], "r"); f1 = fopen (dview->file[1], "r");
}
line = 0; line = 0;
while (fgets (buf, sizeof (buf), f0) != NULL && line < from1 - 1) while (fgets (buf, sizeof (buf), f0) != NULL && line < from1 - 1)
{ {
@ -2113,14 +2129,25 @@ dview_add_hunk (WDiff * dview, FILE * merge_file, int from1, int from2, int to2)
} }
static void static void
dview_replace_hunk (WDiff * dview, FILE * merge_file, int from1, int to1, int from2, int to2) dview_replace_hunk (WDiff * dview, FILE * merge_file, int from1, int to1, int from2, int to2,
gboolean merge_direction)
{ {
int line1, line2; int line1, line2;
char buf[BUF_10K]; char buf[BUF_10K];
FILE *f0; FILE *f0;
FILE *f1; FILE *f1;
if (merge_direction)
{
f0 = fopen (dview->file[1], "r");
f1 = fopen (dview->file[0], "r");
}
else
{
f0 = fopen (dview->file[0], "r"); f0 = fopen (dview->file[0], "r");
f1 = fopen (dview->file[1], "r"); f1 = fopen (dview->file[1], "r");
}
line1 = 0; line1 = 0;
while (fgets (buf, sizeof (buf), f0) != NULL && line1 < from1 - 1) while (fgets (buf, sizeof (buf), f0) != NULL && line1 < from1 - 1)
{ {
@ -2145,27 +2172,32 @@ dview_replace_hunk (WDiff * dview, FILE * merge_file, int from1, int to1, int fr
} }
static void static void
do_merge_hunk (WDiff * dview) do_merge_hunk (WDiff * dview, gboolean merge_direction)
{ {
int from1, to1, from2, to2; int from1, to1, from2, to2;
int res; int res;
int hunk; int hunk;
int n_merge = merge_direction ? 1 : 0;
if (merge_direction)
hunk = get_current_hunk (dview, &from2, &to2, &from1, &to1);
else
hunk = get_current_hunk (dview, &from1, &to1, &from2, &to2); hunk = get_current_hunk (dview, &from1, &to1, &from2, &to2);
if (hunk > 0) if (hunk > 0)
{ {
int merge_file_fd; int merge_file_fd;
FILE *merge_file; FILE *merge_file;
vfs_path_t *merge_file_name_vpath = NULL; vfs_path_t *merge_file_name_vpath = NULL;
if (!dview->merged) if (!dview->merged[n_merge])
{ {
dview->merged = mc_util_make_backup_if_possible (dview->file[0], "~~~"); dview->merged[n_merge] = mc_util_make_backup_if_possible (dview->file[n_merge], "~~~");
if (!dview->merged) if (!dview->merged[n_merge])
{ {
message (D_ERROR, MSG_ERROR, message (D_ERROR, MSG_ERROR,
_("Cannot create backup file\n%s%s\n%s"), _("Cannot create backup file\n%s%s\n%s"),
dview->file[0], "~~~", unix_error_string (errno)); dview->file[n_merge], "~~~", unix_error_string (errno));
return; return;
} }
@ -2184,18 +2216,24 @@ do_merge_hunk (WDiff * dview)
switch (hunk) switch (hunk)
{ {
case DIFF_DEL: case DIFF_DEL:
dview_remove_hunk (dview, merge_file, from1, to1); if (merge_direction)
dview_add_hunk (dview, merge_file, from1, from2, to2, TRUE);
else
dview_remove_hunk (dview, merge_file, from1, to1, FALSE);
break; break;
case DIFF_ADD: case DIFF_ADD:
dview_add_hunk (dview, merge_file, from1, from2, to2); if (merge_direction)
dview_remove_hunk (dview, merge_file, from1, to1, TRUE);
else
dview_add_hunk (dview, merge_file, from1, from2, to2, FALSE);
break; break;
case DIFF_CHG: case DIFF_CHG:
dview_replace_hunk (dview, merge_file, from1, to1, from2, to2); dview_replace_hunk (dview, merge_file, from1, to1, from2, to2, merge_direction);
break; break;
} }
fflush (merge_file); fflush (merge_file);
fclose (merge_file); fclose (merge_file);
res = rewrite_backup_content (merge_file_name_vpath, dview->file[0]); res = rewrite_backup_content (merge_file_name_vpath, dview->file[n_merge]);
mc_unlink (merge_file_name_vpath); mc_unlink (merge_file_name_vpath);
vfs_path_free (merge_file_name_vpath); vfs_path_free (merge_file_name_vpath);
} }
@ -2388,6 +2426,8 @@ dview_init (WDiff * dview, const char *args, const char *file1, const char *file
dview->label[1] = g_strdup (label2); dview->label[1] = g_strdup (label2);
dview->f[0] = f[0]; dview->f[0] = f[0];
dview->f[1] = f[1]; dview->f[1] = f[1];
dview->merged[0] = FALSE;
dview->merged[1] = FALSE;
dview->hdiff = NULL; dview->hdiff = NULL;
dview->dsrc = dsrc; dview->dsrc = dsrc;
dview->converter = str_cnv_from_term; dview->converter = str_cnv_from_term;
@ -2722,7 +2762,7 @@ dview_status (const WDiff * dview, int ord, int width, int c)
tty_gotoyx (0, c); tty_gotoyx (0, c);
get_line_numbers (dview->a[ord], dview->skip_rows, &linenum, &lineofs); get_line_numbers (dview->a[ord], dview->skip_rows, &linenum, &lineofs);
filename_width = width - 22; filename_width = width - 24;
if (filename_width < 8) if (filename_width < 8)
filename_width = 8; filename_width = 8;
@ -2731,10 +2771,11 @@ dview_status (const WDiff * dview, int ord, int width, int c)
vfs_path_free (vpath); vfs_path_free (vpath);
buf = str_term_trim (path, filename_width); buf = str_term_trim (path, filename_width);
if (ord == 0) if (ord == 0)
tty_printf ("%-*s %6d+%-4d Col %-4d ", filename_width, buf, linenum, lineofs, tty_printf ("%s%-*s %6d+%-4d Col %-4d ", dview->merged[ord] ? "* " : " ", filename_width,
dview->skip_cols); buf, linenum, lineofs, dview->skip_cols);
else else
tty_printf ("%-*s %6d+%-4d Dif %-4d ", filename_width, buf, linenum, lineofs, dview->ndiff); tty_printf ("%s%-*s %6d+%-4d Dif %-4d ", dview->merged[ord] ? "* " : " ", filename_width,
buf, linenum, lineofs, dview->ndiff);
g_free (path); g_free (path);
} }
@ -2875,10 +2916,16 @@ static gboolean
dview_save (WDiff * dview) dview_save (WDiff * dview)
{ {
gboolean res = TRUE; gboolean res = TRUE;
if (!dview->merged) if (dview->merged[0])
return res; {
res = mc_util_unlink_backup_if_possible (dview->file[0], "~~~"); res = mc_util_unlink_backup_if_possible (dview->file[0], "~~~");
dview->merged = !res; dview->merged[0] = !res;
}
if (dview->merged[1])
{
res = mc_util_unlink_backup_if_possible (dview->file[1], "~~~");
dview->merged[1] = !res;
}
return res; return res;
} }
@ -2954,12 +3001,12 @@ dview_ok_to_exit (WDiff * dview)
gboolean res = TRUE; gboolean res = TRUE;
int act; int act;
if (!dview->merged) if (!dview->merged[0] && !dview->merged[1])
return res; return res;
act = query_dialog (_("Quit"), !mc_global.midnight_shutdown ? act = query_dialog (_("Quit"), !mc_global.midnight_shutdown ?
_("File was modified. Save with exit?") : _("File(s) was modified. Save with exit?") :
_("Midnight Commander is being shut down.\nSave modified file?"), _("Midnight Commander is being shut down.\nSave modified file(s)?"),
D_NORMAL, 2, _("&Yes"), _("&No")); D_NORMAL, 2, _("&Yes"), _("&No"));
/* Esc is No */ /* Esc is No */
@ -2978,6 +3025,8 @@ dview_ok_to_exit (WDiff * dview)
case 1: /* No */ case 1: /* No */
if (mc_util_restore_from_backup_if_possible (dview->file[0], "~~~")) if (mc_util_restore_from_backup_if_possible (dview->file[0], "~~~"))
res = mc_util_unlink_backup_if_possible (dview->file[0], "~~~"); res = mc_util_unlink_backup_if_possible (dview->file[0], "~~~");
if (mc_util_restore_from_backup_if_possible (dview->file[1], "~~~"))
res = mc_util_unlink_backup_if_possible (dview->file[1], "~~~");
/* fall through */ /* fall through */
default: default:
res = TRUE; res = TRUE;
@ -3061,7 +3110,11 @@ dview_execute_cmd (WDiff * dview, unsigned long command)
dview_edit (dview, dview->ord); dview_edit (dview, dview->ord);
break; break;
case CK_Merge: case CK_Merge:
do_merge_hunk (dview); do_merge_hunk (dview, FALSE);
dview_redo (dview);
break;
case CK_MergeOther:
do_merge_hunk (dview, TRUE);
dview_redo (dview); dview_redo (dview);
break; break;
case CK_EditOther: case CK_EditOther:
@ -3275,7 +3328,8 @@ static char *
dview_get_title (const Dlg_head * h, size_t len) dview_get_title (const Dlg_head * h, size_t len)
{ {
const WDiff *dview = (const WDiff *) find_widget_type (h, dview_callback); const WDiff *dview = (const WDiff *) find_widget_type (h, dview_callback);
const char *modified = dview->merged ? " (*) " : " "; const char *modified = " (*) ";
const char *notmodified = " ";
size_t len1; size_t len1;
GString *title; GString *title;
@ -3283,9 +3337,10 @@ dview_get_title (const Dlg_head * h, size_t len)
title = g_string_sized_new (len); title = g_string_sized_new (len);
g_string_append (title, _("Diff:")); g_string_append (title, _("Diff:"));
g_string_append (title, modified); g_string_append (title, dview->merged[0] ? modified : notmodified);
g_string_append (title, str_term_trim (dview->label[0], len1)); g_string_append (title, str_term_trim (dview->label[0], len1));
g_string_append (title, " | "); g_string_append (title, " | ");
g_string_append (title, dview->merged[1] ? modified : notmodified);
g_string_append (title, str_term_trim (dview->label[1], len1)); g_string_append (title, str_term_trim (dview->label[1], len1));
return g_string_free (title, FALSE); return g_string_free (title, FALSE);

View File

@ -525,6 +525,7 @@ static const global_keymap_ini_t default_diff_keymap[] = {
{"Edit", "f4"}, {"Edit", "f4"},
{"EditOther", "f14"}, {"EditOther", "f14"},
{"Merge", "f5"}, {"Merge", "f5"},
{"MergeOther", "f15"},
{"Search", "f7"}, {"Search", "f7"},
{"SearchContinue", "f17"}, {"SearchContinue", "f17"},
{"Options", "f9"}, {"Options", "f9"},