git-gui: remove .git/CHERRY_PICK_HEAD after committing
[gitweb.git] / lib / mergetool.tcl
index ba9e8cee8c2d2ce7bdb57620b7d3ce4e83f18090..3c8e73bcebea652c11e328169f63a6d9950d6dc2 100644 (file)
@@ -5,33 +5,57 @@ 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"] }
+               1 { set targetquestion [mc "Force resolution to the base version?"] }
+               2 { set targetquestion [mc "Force resolution to this branch?"] }
+               3 { set targetquestion [mc "Force resolution to the other branch?"] }
        }
 
-       set op_question [mc "Force resolution to %s?
-Note that the diff shows only conflicting changes.
+       set op_question [strcat $targetquestion "\n" \
+[mc "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]]
+               [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
+proc merge_stage_workdir {path {lno {}}} {
+       global current_diff_path diff_active
+       global current_diff_side ui_workdir
+
+       if {$diff_active} return
 
-       if {$path eq $current_diff_path} {
-               set after {reshow_diff;}
+       if {$path ne $current_diff_path || $ui_workdir ne $current_diff_side} {
+               show_diff $path $ui_workdir $lno {} [list do_merge_stage_workdir $path]
        } else {
-               set after {}
+               do_merge_stage_workdir $path
+       }
+}
+
+proc do_merge_stage_workdir {path} {
+       global current_diff_path is_conflict_diff
+
+       if {$path ne $current_diff_path} return;
+
+       if {$is_conflict_diff} {
+               if {[ask_popup [mc "File %s seems to have unresolved conflicts, still stage?" \
+                               [short_path $path]]] ne {yes}} {
+                       return
+               }
        }
 
+       merge_add_resolution $path
+}
+
+proc merge_add_resolution {path} {
+       global current_diff_path ui_workdir
+
+       set after [next_diff_after_action $ui_workdir $path {} {^_?U}]
+
        update_index \
                [mc "Adding resolution for %s" [short_path $path]] \
                [list $path] \
@@ -64,7 +88,7 @@ proc merge_load_stages {path cont} {
        set merge_stages(3) {}
        set merge_stages_buf {}
 
-       set merge_stages_fd [eval git_read ls-files -u -z -- $path]
+       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]
@@ -131,6 +155,7 @@ proc merge_resolve_tool2 {} {
        if {$merge_tool_path eq {}} {
                switch -- $tool {
                emerge { set merge_tool_path "emacs" }
+               araxis { set merge_tool_path "compare" }
                default { set merge_tool_path $tool }
                }
        }
@@ -150,6 +175,44 @@ proc merge_resolve_tool2 {} {
 
        # Build the command line
        switch -- $tool {
+       araxis {
+               if {$base_stage ne {}} {
+                       set cmdline [list "$merge_tool_path" -wait -merge -3 -a1 \
+                               -title1:"'$MERGED (Base)'" -title2:"'$MERGED (Local)'" \
+                               -title3:"'$MERGED (Remote)'" \
+                               "$BASE" "$LOCAL" "$REMOTE" "$MERGED"]
+               } else {
+                       set cmdline [list "$merge_tool_path" -wait -2 \
+                                -title1:"'$MERGED (Local)'" -title2:"'$MERGED (Remote)'" \
+                                "$LOCAL" "$REMOTE" "$MERGED"]
+               }
+       }
+       bc3 {
+               if {$base_stage ne {}} {
+                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" -mergeoutput="$MERGED"]
+               } else {
+                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -mergeoutput="$MERGED"]
+               }
+       }
+       ecmerge {
+               if {$base_stage ne {}} {
+                       set cmdline [list "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" --default --mode=merge3 --to="$MERGED"]
+               } else {
+                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" --default --mode=merge2 --to="$MERGED"]
+               }
+       }
+       emerge {
+               if {$base_stage ne {}} {
+                       set cmdline [list "$merge_tool_path" -f emerge-files-with-ancestor-command \
+                                       "$LOCAL" "$REMOTE" "$BASE" "$basename"]
+               } else {
+                       set cmdline [list "$merge_tool_path" -f emerge-files-command \
+                                       "$LOCAL" "$REMOTE" "$basename"]
+               }
+       }
+       gvimdiff {
+               set cmdline [list "$merge_tool_path" -f "$LOCAL" "$MERGED" "$REMOTE"]
+       }
        kdiff3 {
                if {$base_stage ne {}} {
                        set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Base)" \
@@ -159,6 +222,19 @@ proc merge_resolve_tool2 {} {
                                --L2 "$MERGED (Remote)" -o "$MERGED" "$LOCAL" "$REMOTE"]
                }
        }
+       meld {
+               set cmdline [list "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"]
+       }
+       opendiff {
+               if {$base_stage ne {}} {
+                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED"]
+               } else {
+                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -merge "$MERGED"]
+               }
+       }
+       p4merge {
+               set cmdline [list "$merge_tool_path" "$BASE" "$REMOTE" "$LOCAL" "$MERGED"]
+       }
        tkdiff {
                if {$base_stage ne {}} {
                        set cmdline [list "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"]
@@ -166,11 +242,19 @@ proc merge_resolve_tool2 {} {
                        set cmdline [list "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"]
                }
        }
-       meld {
-               set cmdline [list "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"]
+       vimdiff {
+               error_popup [mc "Not a GUI merge tool: '%s'" $tool]
+               return
        }
-       gvimdiff {
-               set cmdline [list "$merge_tool_path" -f "$LOCAL" "$MERGED" "$REMOTE"]
+       winmerge {
+               if {$base_stage ne {}} {
+                       # This tool does not support 3-way merges.
+                       # Use the 'conflict file' resolution feature instead.
+                       set cmdline [list "$merge_tool_path" -e -ub "$MERGED"]
+               } else {
+                       set cmdline [list "$merge_tool_path" -e -ub -wl \
+                               -dl "Theirs File" -dr "Mine File" "$REMOTE" "$LOCAL" "$MERGED"]
+               }
        }
        xxdiff {
                if {$base_stage ne {}} {
@@ -187,33 +271,6 @@ proc merge_resolve_tool2 {} {
                                            --merged-file "$MERGED" "$LOCAL" "$REMOTE"]
                }
        }
-       opendiff {
-               if {$base_stage ne {}} {
-                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED"]
-               } else {
-                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -merge "$MERGED"]
-               }
-       }
-       ecmerge {
-               if {$base_stage ne {}} {
-                       set cmdline [list "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" --default --mode=merge3 --to="$MERGED"]
-               } else {
-                       set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" --default --mode=merge2 --to="$MERGED"]
-               }
-       }
-       emerge {
-               if {$base_stage ne {}} {
-                       set cmdline [list "$merge_tool_path" -f emerge-files-with-ancestor-command \
-                                       "$LOCAL" "$REMOTE" "$BASE" "$basename"]
-               } else {
-                       set cmdline [list "$merge_tool_path" -f emerge-files-command \
-                                       "$LOCAL" "$REMOTE" "$basename"]
-               }
-       }
-       vimdiff {
-               error_popup [mc "Not a GUI merge tool: '%s'" $tool]
-               return
-       }
        default {
                error_popup [mc "Unsupported merge tool '%s'" $tool]
                return
@@ -236,6 +293,7 @@ proc merge_tool_get_stages {target stages} {
        foreach fname $stages {
                if {$merge_stages($i) eq {}} {
                        file delete $fname
+                       catch { close [open $fname w] }
                } else {
                        # A hack to support autocrlf properly
                        git checkout-index -f --stage=$i -- $target
@@ -325,26 +383,18 @@ proc merge_tool_finish {fd} {
                }
        }
 
-       # Check the modification time of the target file
-       if {!$failed && [file mtime $mtool_target] eq $mtool_mtime} {
-               if {[ask_popup [mc "File %s unchanged, still accept as resolved?" \
-                               [short_path $mtool_target]]] ne {yes}} {
-                       set failed 1
-               }
-       }
-
        # Finish
        if {$failed} {
                file rename -force -- $backup $mtool_target
                delete_temp_files $mtool_tmpfiles
                ui_status [mc "Merge tool failed."]
        } else {
-               if {[is_config_true merge.keepbackup]} {
+               if {[is_config_true mergetool.keepbackup]} {
                        file rename -force -- $backup "$mtool_target.orig"
                }
 
                delete_temp_files $mtool_tmpfiles
 
-               merge_add_resolution $mtool_target
+               reshow_diff
        }
 }