@matheusbsbs / matheus-bagliano / commits / 042c232535
Fork 0

git-gui: Support resolving conflicts via the diff context menu.

If the file has merge conflicts, show a special version of the diff context menu, which includes conflict resolution commands instead of Stage Hunk/Line. This patch only supports resolving by discarding all sides except one. Discarding is the only way to resolve conflicts involving symlinks and/or deletion, excluding manual editing. Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

Alexander Gavrilov committed Aug 31, 2008 at 00:55 UTC 042c232535c329f168e8a515588f38a4117954fb
2 files changed +190 -60
git-gui.sh
+92 -60
@@ -2713,6 +2713,51 @@ $ui_diff tag raise sel
2713
2714 # -- Diff Body Context Menu
2715 #
2716 +
2717 +proc create_common_diff_popup {ctxm} {
2718 + $ctxm add command \
2719 + -label [mc "Show Less Context"] \
2720 + -command show_less_context
2721 + lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2722 + $ctxm add command \
2723 + -label [mc "Show More Context"] \
2724 + -command show_more_context
2725 + lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2726 + $ctxm add separator
2727 + $ctxm add command \
2728 + -label [mc Refresh] \
2729 + -command reshow_diff
2730 + lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2731 + $ctxm add command \
2732 + -label [mc Copy] \
2733 + -command {tk_textCopy $ui_diff}
2734 + lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2735 + $ctxm add command \
2736 + -label [mc "Select All"] \
2737 + -command {focus $ui_diff;$ui_diff tag add sel 0.0 end}
2738 + lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2739 + $ctxm add command \
2740 + -label [mc "Copy All"] \
2741 + -command {
2742 + $ui_diff tag add sel 0.0 end
2743 + tk_textCopy $ui_diff
2744 + $ui_diff tag remove sel 0.0 end
2745 + }
2746 + lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2747 + $ctxm add separator
2748 + $ctxm add command \
2749 + -label [mc "Decrease Font Size"] \
2750 + -command {incr_font_size font_diff -1}
2751 + lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2752 + $ctxm add command \
2753 + -label [mc "Increase Font Size"] \
2754 + -command {incr_font_size font_diff 1}
2755 + lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2756 + $ctxm add separator
2757 + $ctxm add command -label [mc "Options..."] \
2758 + -command do_options
2759 +}
2760 +
2761 set ctxm .vpane.lower.diff.body.ctxm
2762 menu $ctxm -tearoff 0
2763 $ctxm add command \
@@ -2726,73 +2771,60 @@ $ctxm add command \
2771 set ui_diff_applyline [$ctxm index last]
2772 lappend diff_actions [list $ctxm entryconf $ui_diff_applyline -state]
2773 $ctxm add separator
2729 -$ctxm add command \
2730 - -label [mc "Show Less Context"] \
2731 - -command show_less_context
2732 -lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2733 -$ctxm add command \
2734 - -label [mc "Show More Context"] \
2735 - -command show_more_context
2736 -lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2737 -$ctxm add separator
2738 -$ctxm add command \
2739 - -label [mc Refresh] \
2740 - -command reshow_diff
2741 -lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2742 -$ctxm add command \
2743 - -label [mc Copy] \
2744 - -command {tk_textCopy $ui_diff}
2745 -lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2746 -$ctxm add command \
2747 - -label [mc "Select All"] \
2748 - -command {focus $ui_diff;$ui_diff tag add sel 0.0 end}
2749 -lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2750 -$ctxm add command \
2751 - -label [mc "Copy All"] \
2752 - -command {
2753 - $ui_diff tag add sel 0.0 end
2754 - tk_textCopy $ui_diff
2755 - $ui_diff tag remove sel 0.0 end
2756 - }
2757 -lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2758 -$ctxm add separator
2759 -$ctxm add command \
2760 - -label [mc "Decrease Font Size"] \
2761 - -command {incr_font_size font_diff -1}
2762 -lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2763 -$ctxm add command \
2764 - -label [mc "Increase Font Size"] \
2765 - -command {incr_font_size font_diff 1}
2766 -lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
2767 -$ctxm add separator
2768 -$ctxm add command -label [mc "Options..."] \
2769 - -command do_options
2770 -proc popup_diff_menu {ctxm x y X Y} {
2774 +create_common_diff_popup $ctxm
2775 +
2776 +set ctxmmg .vpane.lower.diff.body.ctxmmg
2777 +menu $ctxmmg -tearoff 0
2778 +$ctxmmg add command \
2779 + -label [mc "Use Remote Version"] \
2780 + -command {merge_resolve_one 3}
2781 +lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
2782 +$ctxmmg add command \
2783 + -label [mc "Use Local Version"] \
2784 + -command {merge_resolve_one 2}
2785 +lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
2786 +$ctxmmg add command \
2787 + -label [mc "Revert To Base"] \
2788 + -command {merge_resolve_one 1}
2789 +lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
2790 +$ctxmmg add separator
2791 +create_common_diff_popup $ctxmmg
2792 +
2793 +proc popup_diff_menu {ctxm ctxmmg x y X Y} {
2794 global current_diff_path file_states
2795 set ::cursorX $x
2796 set ::cursorY $y
2774 - if {$::ui_index eq $::current_diff_side} {
2775 - set l [mc "Unstage Hunk From Commit"]
2776 - set t [mc "Unstage Line From Commit"]
2797 + if {[info exists file_states($current_diff_path)]} {
2798 + set state [lindex $file_states($current_diff_path) 0]
2799 } else {
2778 - set l [mc "Stage Hunk For Commit"]
2779 - set t [mc "Stage Line For Commit"]
2780 - }
2781 - if {$::is_3way_diff
2782 - || $current_diff_path eq {}
2783 - || ![info exists file_states($current_diff_path)]
2784 - || {_O} eq [lindex $file_states($current_diff_path) 0]
2785 - || {_T} eq [lindex $file_states($current_diff_path) 0]
2786 - || {T_} eq [lindex $file_states($current_diff_path) 0]} {
2787 - set s disabled
2800 + set state {__}
2801 + }
2802 + if {[string index $state 0] eq {U}} {
2803 + tk_popup $ctxmmg $X $Y
2804 } else {
2789 - set s normal
2805 + if {$::ui_index eq $::current_diff_side} {
2806 + set l [mc "Unstage Hunk From Commit"]
2807 + set t [mc "Unstage Line From Commit"]
2808 + } else {
2809 + set l [mc "Stage Hunk For Commit"]
2810 + set t [mc "Stage Line For Commit"]
2811 + }
2812 + if {$::is_3way_diff
2813 + || $current_diff_path eq {}
2814 + || {__} eq $state
2815 + || {_O} eq $state
2816 + || {_T} eq $state
2817 + || {T_} eq $state} {
2818 + set s disabled
2819 + } else {
2820 + set s normal
2821 + }
2822 + $ctxm entryconf $::ui_diff_applyhunk -state $s -label $l
2823 + $ctxm entryconf $::ui_diff_applyline -state $s -label $t
2824 + tk_popup $ctxm $X $Y
2825 }
2791 - $ctxm entryconf $::ui_diff_applyhunk -state $s -label $l
2792 - $ctxm entryconf $::ui_diff_applyline -state $s -label $t
2793 - tk_popup $ctxm $X $Y
2826 }
2795 -bind_button3 $ui_diff [list popup_diff_menu $ctxm %x %y %X %Y]
2827 +bind_button3 $ui_diff [list popup_diff_menu $ctxm $ctxmmg %x %y %X %Y]
2828
2829 # -- Status Bar
2830 #
lib/mergetool.tcl new
+98
@@ -0,0 +1,98 @@
1 +# git-gui merge conflict resolution
2 +# parts based on git-mergetool (c) 2006 Theodore Y. Ts'o
3 +
4 +proc merge_resolve_one {stage} {
5 + global current_diff_path
6 +
7 + switch -- $stage {
8 + 1 { set target [mc "the base version"] }
9 + 2 { set target [mc "this branch"] }
10 + 3 { set target [mc "the other branch"] }
11 + }
12 +
13 + set op_question [mc "Force resolution to %s?
14 +Note that the diff shows only conflicting changes.
15 +
16 +%s will be overwritten.
17 +
18 +This operation can be undone only by restarting the merge." \
19 + $target [short_path $current_diff_path]]
20 +
21 + if {[ask_popup $op_question] eq {yes}} {
22 + merge_load_stages $current_diff_path [list merge_force_stage $stage]
23 + }
24 +}
25 +
26 +proc merge_add_resolution {path} {
27 + global current_diff_path
28 +
29 + if {$path eq $current_diff_path} {
30 + set after {reshow_diff;}
31 + } else {
32 + set after {}
33 + }
34 +
35 + update_index \
36 + [mc "Adding resolution for %s" [short_path $path]] \
37 + [list $path] \
38 + [concat $after [list ui_ready]]
39 +}
40 +
41 +proc merge_force_stage {stage} {
42 + global current_diff_path merge_stages
43 +
44 + if {$merge_stages($stage) ne {}} {
45 + git checkout-index -f --stage=$stage -- $current_diff_path
46 + } else {
47 + file delete -- $current_diff_path
48 + }
49 +
50 + merge_add_resolution $current_diff_path
51 +}
52 +
53 +proc merge_load_stages {path cont} {
54 + global merge_stages_fd merge_stages merge_stages_buf
55 +
56 + if {[info exists merge_stages_fd]} {
57 + catch { kill_file_process $merge_stages_fd }
58 + catch { close $merge_stages_fd }
59 + }
60 +
61 + set merge_stages(0) {}
62 + set merge_stages(1) {}
63 + set merge_stages(2) {}
64 + set merge_stages(3) {}
65 + set merge_stages_buf {}
66 +
67 + set merge_stages_fd [eval git_read ls-files -u -z -- $path]
68 +
69 + fconfigure $merge_stages_fd -blocking 0 -translation binary -encoding binary
70 + fileevent $merge_stages_fd readable [list read_merge_stages $merge_stages_fd $cont]
71 +}
72 +
73 +proc read_merge_stages {fd cont} {
74 + global merge_stages_buf merge_stages_fd merge_stages
75 +
76 + append merge_stages_buf [read $fd]
77 + set pck [split $merge_stages_buf "\0"]
78 + set merge_stages_buf [lindex $pck end]
79 +
80 + if {[eof $fd] && $merge_stages_buf ne {}} {
81 + lappend pck {}
82 + set merge_stages_buf {}
83 + }
84 +
85 + foreach p [lrange $pck 0 end-1] {
86 + set fcols [split $p "\t"]
87 + set cols [split [lindex $fcols 0] " "]
88 + set stage [lindex $cols 2]
89 +
90 + set merge_stages($stage) [lrange $cols 0 1]
91 + }
92 +
93 + if {[eof $fd]} {
94 + close $fd
95 + unset merge_stages_fd
96 + eval $cont
97 + }
98 +}