From: Alexander Gavrilov <angavrilov@gmail.com>
To: git@vger.kernel.org
Cc: "Shawn O. Pearce" <spearce@spearce.org>
Subject: [PATCH (GIT-GUI) 2/8] git-gui: Support resolving conflicts via the diff context menu.
Date: Sun, 31 Aug 2008 00:55:45 +0400 [thread overview]
Message-ID: <200808310055.45679.angavrilov@gmail.com> (raw)
In-Reply-To: <200808310054.19732.angavrilov@gmail.com>
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>
---
git-gui.sh | 152 ++++++++++++++++++++++++++++++++---------------------
lib/mergetool.tcl | 98 ++++++++++++++++++++++++++++++++++
2 files changed, 190 insertions(+), 60 deletions(-)
create mode 100644 lib/mergetool.tcl
diff --git a/git-gui.sh b/git-gui.sh
index 9df4f8c..90d597e 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -2721,6 +2721,51 @@ $ui_diff tag raise sel
# -- 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
menu $ctxm -tearoff 0
$ctxm add command \
@@ -2734,73 +2779,60 @@ $ctxm add command \
set ui_diff_applyline [$ctxm index last]
lappend diff_actions [list $ctxm entryconf $ui_diff_applyline -state]
$ctxm add separator
-$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
-proc popup_diff_menu {ctxm x y X Y} {
+create_common_diff_popup $ctxm
+
+set ctxmmg .vpane.lower.diff.body.ctxmmg
+menu $ctxmmg -tearoff 0
+$ctxmmg add command \
+ -label [mc "Use Remote Version"] \
+ -command {merge_resolve_one 3}
+lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
+$ctxmmg add command \
+ -label [mc "Use Local Version"] \
+ -command {merge_resolve_one 2}
+lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
+$ctxmmg add command \
+ -label [mc "Revert To Base"] \
+ -command {merge_resolve_one 1}
+lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state]
+$ctxmmg add separator
+create_common_diff_popup $ctxmmg
+
+proc popup_diff_menu {ctxm ctxmmg x y X Y} {
global current_diff_path file_states
set ::cursorX $x
set ::cursorY $y
- if {$::ui_index eq $::current_diff_side} {
- set l [mc "Unstage Hunk From Commit"]
- set t [mc "Unstage Line From Commit"]
+ if {[info exists file_states($current_diff_path)]} {
+ set state [lindex $file_states($current_diff_path) 0]
} else {
- set l [mc "Stage Hunk For Commit"]
- set t [mc "Stage Line For Commit"]
- }
- if {$::is_3way_diff
- || $current_diff_path eq {}
- || ![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
+ set state {__}
+ }
+ if {[string index $state 0] eq {U}} {
+ tk_popup $ctxmmg $X $Y
} 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
#
diff --git a/lib/mergetool.tcl b/lib/mergetool.tcl
new file mode 100644
index 0000000..7945d74
--- /dev/null
+++ b/lib/mergetool.tcl
@@ -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
+ }
+}
--
1.6.0.20.g6148bc
next prev parent reply other threads:[~2008-08-30 21:16 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-30 20:52 [PATCH (GIT-GUI) 0/8] Add mergetool functionality to git-gui Alexander Gavrilov
2008-08-30 20:54 ` [PATCH (GIT-GUI) 1/8] git-gui: Don't allow staging files with conflicts Alexander Gavrilov
2008-08-30 20:55 ` Alexander Gavrilov [this message]
2008-08-30 20:56 ` [PATCH (GIT-GUI) 3/8] git-gui: Support calling merge tools Alexander Gavrilov
2008-08-30 20:59 ` [PATCH (GIT-GUI) 4/8] git-gui: Support more " Alexander Gavrilov
2008-08-30 21:00 ` [PATCH (GIT-GUI) 5/8] git-gui: Support conflict states _U & UT Alexander Gavrilov
2008-08-30 21:02 ` [PATCH (GIT-GUI) 6/8] git-gui: Reimplement and enhance auto-selection of diffs Alexander Gavrilov
2008-08-30 21:04 ` [PATCH (GIT-GUI) 7/8] git-gui: Make F5 reselect a diff, if an untracked file is selected Alexander Gavrilov
2008-08-30 21:05 ` [PATCH (GIT-GUI) 8/8] git-gui: Show special diffs for complex conflict cases Alexander Gavrilov
2008-09-08 12:10 ` [PATCH (GIT-GUI) 1/8] git-gui: Don't allow staging files with conflicts Johannes Sixt
2008-09-08 12:25 ` Alexander Gavrilov
2008-09-17 11:40 ` [PATCH/RFC 0/2] git-gui: issues with merge tool series Johannes Sixt
2008-09-17 11:40 ` [PATCH/RFC 1/2] Revert "git-gui: Don't allow staging files with conflicts." Johannes Sixt
2008-09-17 11:40 ` [PATCH/RFC 2/2] git-gui: Do not automatically stage file after merge tool finishes Johannes Sixt
2008-09-17 12:25 ` Alexander Gavrilov
2008-09-24 17:50 ` Shawn O. Pearce
2008-09-24 19:08 ` [PATCH/RFC 2/2 v2] " Johannes Sixt
2008-09-17 12:50 ` [PATCH/RFC 0/2] git-gui: issues with merge tool series Alexander Gavrilov
2008-09-17 21:40 ` Johannes Sixt
2008-09-17 22:24 ` Alexander Gavrilov
2008-09-24 17:48 ` Shawn O. Pearce
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200808310055.45679.angavrilov@gmail.com \
--to=angavrilov@gmail.com \
--cc=git@vger.kernel.org \
--cc=spearce@spearce.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).