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>
This commit is contained in:

committed by
Shawn O. Pearce

parent
700e560341
commit
042c232535
150
git-gui.sh
150
git-gui.sh
@ -2713,6 +2713,51 @@ $ui_diff tag raise sel
|
|||||||
|
|
||||||
# -- Diff Body Context Menu
|
# -- Diff Body Context Menu
|
||||||
#
|
#
|
||||||
|
|
||||||
|
proc create_common_diff_popup {ctxm} {
|
||||||
|
$ctxm add command \
|
||||||
|
-label [mc "Show Less Context"] \
|
||||||
|
-command show_less_context
|
||||||
|
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
||||||
|
$ctxm add command \
|
||||||
|
-label [mc "Show More Context"] \
|
||||||
|
-command show_more_context
|
||||||
|
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
||||||
|
$ctxm add separator
|
||||||
|
$ctxm add command \
|
||||||
|
-label [mc Refresh] \
|
||||||
|
-command reshow_diff
|
||||||
|
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
||||||
|
$ctxm add command \
|
||||||
|
-label [mc Copy] \
|
||||||
|
-command {tk_textCopy $ui_diff}
|
||||||
|
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
||||||
|
$ctxm add command \
|
||||||
|
-label [mc "Select All"] \
|
||||||
|
-command {focus $ui_diff;$ui_diff tag add sel 0.0 end}
|
||||||
|
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
||||||
|
$ctxm add command \
|
||||||
|
-label [mc "Copy All"] \
|
||||||
|
-command {
|
||||||
|
$ui_diff tag add sel 0.0 end
|
||||||
|
tk_textCopy $ui_diff
|
||||||
|
$ui_diff tag remove sel 0.0 end
|
||||||
|
}
|
||||||
|
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
||||||
|
$ctxm add separator
|
||||||
|
$ctxm add command \
|
||||||
|
-label [mc "Decrease Font Size"] \
|
||||||
|
-command {incr_font_size font_diff -1}
|
||||||
|
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
||||||
|
$ctxm add command \
|
||||||
|
-label [mc "Increase Font Size"] \
|
||||||
|
-command {incr_font_size font_diff 1}
|
||||||
|
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
||||||
|
$ctxm add separator
|
||||||
|
$ctxm add command -label [mc "Options..."] \
|
||||||
|
-command do_options
|
||||||
|
}
|
||||||
|
|
||||||
set ctxm .vpane.lower.diff.body.ctxm
|
set ctxm .vpane.lower.diff.body.ctxm
|
||||||
menu $ctxm -tearoff 0
|
menu $ctxm -tearoff 0
|
||||||
$ctxm add command \
|
$ctxm add command \
|
||||||
@ -2726,73 +2771,60 @@ $ctxm add command \
|
|||||||
set ui_diff_applyline [$ctxm index last]
|
set ui_diff_applyline [$ctxm index last]
|
||||||
lappend diff_actions [list $ctxm entryconf $ui_diff_applyline -state]
|
lappend diff_actions [list $ctxm entryconf $ui_diff_applyline -state]
|
||||||
$ctxm add separator
|
$ctxm add separator
|
||||||
$ctxm add command \
|
create_common_diff_popup $ctxm
|
||||||
-label [mc "Show Less Context"] \
|
|
||||||
-command show_less_context
|
set ctxmmg .vpane.lower.diff.body.ctxmmg
|
||||||
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
menu $ctxmmg -tearoff 0
|
||||||
$ctxm add command \
|
$ctxmmg add command \
|
||||||
-label [mc "Show More Context"] \
|
-label [mc "Use Remote Version"] \
|
||||||
-command show_more_context
|
-command {merge_resolve_one 3}
|
||||||
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
|
||||||
$ctxm add separator
|
$ctxmmg add command \
|
||||||
$ctxm add command \
|
-label [mc "Use Local Version"] \
|
||||||
-label [mc Refresh] \
|
-command {merge_resolve_one 2}
|
||||||
-command reshow_diff
|
lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
|
||||||
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
$ctxmmg add command \
|
||||||
$ctxm add command \
|
-label [mc "Revert To Base"] \
|
||||||
-label [mc Copy] \
|
-command {merge_resolve_one 1}
|
||||||
-command {tk_textCopy $ui_diff}
|
lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
|
||||||
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
$ctxmmg add separator
|
||||||
$ctxm add command \
|
create_common_diff_popup $ctxmmg
|
||||||
-label [mc "Select All"] \
|
|
||||||
-command {focus $ui_diff;$ui_diff tag add sel 0.0 end}
|
proc popup_diff_menu {ctxm ctxmmg x y X Y} {
|
||||||
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
|
||||||
$ctxm add command \
|
|
||||||
-label [mc "Copy All"] \
|
|
||||||
-command {
|
|
||||||
$ui_diff tag add sel 0.0 end
|
|
||||||
tk_textCopy $ui_diff
|
|
||||||
$ui_diff tag remove sel 0.0 end
|
|
||||||
}
|
|
||||||
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
|
||||||
$ctxm add separator
|
|
||||||
$ctxm add command \
|
|
||||||
-label [mc "Decrease Font Size"] \
|
|
||||||
-command {incr_font_size font_diff -1}
|
|
||||||
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
|
||||||
$ctxm add command \
|
|
||||||
-label [mc "Increase Font Size"] \
|
|
||||||
-command {incr_font_size font_diff 1}
|
|
||||||
lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
|
|
||||||
$ctxm add separator
|
|
||||||
$ctxm add command -label [mc "Options..."] \
|
|
||||||
-command do_options
|
|
||||||
proc popup_diff_menu {ctxm x y X Y} {
|
|
||||||
global current_diff_path file_states
|
global current_diff_path file_states
|
||||||
set ::cursorX $x
|
set ::cursorX $x
|
||||||
set ::cursorY $y
|
set ::cursorY $y
|
||||||
if {$::ui_index eq $::current_diff_side} {
|
if {[info exists file_states($current_diff_path)]} {
|
||||||
set l [mc "Unstage Hunk From Commit"]
|
set state [lindex $file_states($current_diff_path) 0]
|
||||||
set t [mc "Unstage Line From Commit"]
|
|
||||||
} else {
|
} else {
|
||||||
set l [mc "Stage Hunk For Commit"]
|
set state {__}
|
||||||
set t [mc "Stage Line For Commit"]
|
|
||||||
}
|
}
|
||||||
if {$::is_3way_diff
|
if {[string index $state 0] eq {U}} {
|
||||||
|| $current_diff_path eq {}
|
tk_popup $ctxmmg $X $Y
|
||||||
|| ![info exists file_states($current_diff_path)]
|
|
||||||
|| {_O} eq [lindex $file_states($current_diff_path) 0]
|
|
||||||
|| {_T} eq [lindex $file_states($current_diff_path) 0]
|
|
||||||
|| {T_} eq [lindex $file_states($current_diff_path) 0]} {
|
|
||||||
set s disabled
|
|
||||||
} else {
|
} else {
|
||||||
set s normal
|
if {$::ui_index eq $::current_diff_side} {
|
||||||
|
set l [mc "Unstage Hunk From Commit"]
|
||||||
|
set t [mc "Unstage Line From Commit"]
|
||||||
|
} else {
|
||||||
|
set l [mc "Stage Hunk For Commit"]
|
||||||
|
set t [mc "Stage Line For Commit"]
|
||||||
|
}
|
||||||
|
if {$::is_3way_diff
|
||||||
|
|| $current_diff_path eq {}
|
||||||
|
|| {__} eq $state
|
||||||
|
|| {_O} eq $state
|
||||||
|
|| {_T} eq $state
|
||||||
|
|| {T_} eq $state} {
|
||||||
|
set s disabled
|
||||||
|
} else {
|
||||||
|
set s normal
|
||||||
|
}
|
||||||
|
$ctxm entryconf $::ui_diff_applyhunk -state $s -label $l
|
||||||
|
$ctxm entryconf $::ui_diff_applyline -state $s -label $t
|
||||||
|
tk_popup $ctxm $X $Y
|
||||||
}
|
}
|
||||||
$ctxm entryconf $::ui_diff_applyhunk -state $s -label $l
|
|
||||||
$ctxm entryconf $::ui_diff_applyline -state $s -label $t
|
|
||||||
tk_popup $ctxm $X $Y
|
|
||||||
}
|
}
|
||||||
bind_button3 $ui_diff [list popup_diff_menu $ctxm %x %y %X %Y]
|
bind_button3 $ui_diff [list popup_diff_menu $ctxm $ctxmmg %x %y %X %Y]
|
||||||
|
|
||||||
# -- Status Bar
|
# -- Status Bar
|
||||||
#
|
#
|
||||||
|
98
lib/mergetool.tcl
Normal file
98
lib/mergetool.tcl
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
# git-gui merge conflict resolution
|
||||||
|
# parts based on git-mergetool (c) 2006 Theodore Y. Ts'o
|
||||||
|
|
||||||
|
proc merge_resolve_one {stage} {
|
||||||
|
global current_diff_path
|
||||||
|
|
||||||
|
switch -- $stage {
|
||||||
|
1 { set target [mc "the base version"] }
|
||||||
|
2 { set target [mc "this branch"] }
|
||||||
|
3 { set target [mc "the other branch"] }
|
||||||
|
}
|
||||||
|
|
||||||
|
set op_question [mc "Force resolution to %s?
|
||||||
|
Note that the diff shows only conflicting changes.
|
||||||
|
|
||||||
|
%s will be overwritten.
|
||||||
|
|
||||||
|
This operation can be undone only by restarting the merge." \
|
||||||
|
$target [short_path $current_diff_path]]
|
||||||
|
|
||||||
|
if {[ask_popup $op_question] eq {yes}} {
|
||||||
|
merge_load_stages $current_diff_path [list merge_force_stage $stage]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proc merge_add_resolution {path} {
|
||||||
|
global current_diff_path
|
||||||
|
|
||||||
|
if {$path eq $current_diff_path} {
|
||||||
|
set after {reshow_diff;}
|
||||||
|
} else {
|
||||||
|
set after {}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_index \
|
||||||
|
[mc "Adding resolution for %s" [short_path $path]] \
|
||||||
|
[list $path] \
|
||||||
|
[concat $after [list ui_ready]]
|
||||||
|
}
|
||||||
|
|
||||||
|
proc merge_force_stage {stage} {
|
||||||
|
global current_diff_path merge_stages
|
||||||
|
|
||||||
|
if {$merge_stages($stage) ne {}} {
|
||||||
|
git checkout-index -f --stage=$stage -- $current_diff_path
|
||||||
|
} else {
|
||||||
|
file delete -- $current_diff_path
|
||||||
|
}
|
||||||
|
|
||||||
|
merge_add_resolution $current_diff_path
|
||||||
|
}
|
||||||
|
|
||||||
|
proc merge_load_stages {path cont} {
|
||||||
|
global merge_stages_fd merge_stages merge_stages_buf
|
||||||
|
|
||||||
|
if {[info exists merge_stages_fd]} {
|
||||||
|
catch { kill_file_process $merge_stages_fd }
|
||||||
|
catch { close $merge_stages_fd }
|
||||||
|
}
|
||||||
|
|
||||||
|
set merge_stages(0) {}
|
||||||
|
set merge_stages(1) {}
|
||||||
|
set merge_stages(2) {}
|
||||||
|
set merge_stages(3) {}
|
||||||
|
set merge_stages_buf {}
|
||||||
|
|
||||||
|
set merge_stages_fd [eval git_read ls-files -u -z -- $path]
|
||||||
|
|
||||||
|
fconfigure $merge_stages_fd -blocking 0 -translation binary -encoding binary
|
||||||
|
fileevent $merge_stages_fd readable [list read_merge_stages $merge_stages_fd $cont]
|
||||||
|
}
|
||||||
|
|
||||||
|
proc read_merge_stages {fd cont} {
|
||||||
|
global merge_stages_buf merge_stages_fd merge_stages
|
||||||
|
|
||||||
|
append merge_stages_buf [read $fd]
|
||||||
|
set pck [split $merge_stages_buf "\0"]
|
||||||
|
set merge_stages_buf [lindex $pck end]
|
||||||
|
|
||||||
|
if {[eof $fd] && $merge_stages_buf ne {}} {
|
||||||
|
lappend pck {}
|
||||||
|
set merge_stages_buf {}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach p [lrange $pck 0 end-1] {
|
||||||
|
set fcols [split $p "\t"]
|
||||||
|
set cols [split [lindex $fcols 0] " "]
|
||||||
|
set stage [lindex $cols 2]
|
||||||
|
|
||||||
|
set merge_stages($stage) [lrange $cols 0 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[eof $fd]} {
|
||||||
|
close $fd
|
||||||
|
unset merge_stages_fd
|
||||||
|
eval $cont
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user