gitk: Unify handling of merge diffs with normal 2-way diffs
This adds code to getblobdiffline to make it able to recognize and display merge diffs (i.e. N-way diffs for N >= 3) as well as normal two-way diffs. This means that it can also correctly display the 3-way diff of the local changes when the git repository is in the middle of a merge with conflicts. This also removes getmergediffline and changes mergediff to invoke getblobdiffline rather than getmergediffline. Signed-off-by: Paul Mackerras <paulus@samba.org>maint
parent
e3e901bece
commit
8b07dca18a
270
gitk
270
gitk
|
@ -2098,7 +2098,7 @@ proc makewindow {} {
|
||||||
$ctext tag conf filesep -font textfontbold -back "#aaaaaa"
|
$ctext tag conf filesep -font textfontbold -back "#aaaaaa"
|
||||||
$ctext tag conf hunksep -fore [lindex $diffcolors 2]
|
$ctext tag conf hunksep -fore [lindex $diffcolors 2]
|
||||||
$ctext tag conf d0 -fore [lindex $diffcolors 0]
|
$ctext tag conf d0 -fore [lindex $diffcolors 0]
|
||||||
$ctext tag conf d1 -fore [lindex $diffcolors 1]
|
$ctext tag conf dresult -fore [lindex $diffcolors 1]
|
||||||
$ctext tag conf m0 -fore red
|
$ctext tag conf m0 -fore red
|
||||||
$ctext tag conf m1 -fore blue
|
$ctext tag conf m1 -fore blue
|
||||||
$ctext tag conf m2 -fore green
|
$ctext tag conf m2 -fore green
|
||||||
|
@ -3217,7 +3217,7 @@ proc find_hunk_blamespec {base line} {
|
||||||
}
|
}
|
||||||
|
|
||||||
proc external_blame_diff {} {
|
proc external_blame_diff {} {
|
||||||
global currentid diffmergeid cmitmode
|
global currentid cmitmode
|
||||||
global diff_menu_txtpos diff_menu_line
|
global diff_menu_txtpos diff_menu_line
|
||||||
global diff_menu_filebase flist_menu_file
|
global diff_menu_filebase flist_menu_file
|
||||||
|
|
||||||
|
@ -6668,130 +6668,16 @@ proc mark_ctext_line {lnum} {
|
||||||
}
|
}
|
||||||
|
|
||||||
proc mergediff {id} {
|
proc mergediff {id} {
|
||||||
global diffmergeid mdifffd
|
global diffmergeid
|
||||||
global diffids treediffs
|
global diffids treediffs
|
||||||
global parents
|
global parents curview
|
||||||
global diffcontext
|
|
||||||
global diffencoding
|
|
||||||
global limitdiffs vfilelimit curview
|
|
||||||
global targetline
|
|
||||||
|
|
||||||
set diffmergeid $id
|
set diffmergeid $id
|
||||||
set diffids $id
|
set diffids $id
|
||||||
set treediffs($id) {}
|
set treediffs($id) {}
|
||||||
set targetline {}
|
|
||||||
# this doesn't seem to actually affect anything...
|
|
||||||
set cmd [concat | git diff-tree --no-commit-id --cc -U$diffcontext $id]
|
|
||||||
if {$limitdiffs && $vfilelimit($curview) ne {}} {
|
|
||||||
set cmd [concat $cmd -- $vfilelimit($curview)]
|
|
||||||
}
|
|
||||||
if {[catch {set mdf [open $cmd r]} err]} {
|
|
||||||
error_popup "[mc "Error getting merge diffs:"] $err"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fconfigure $mdf -blocking 0 -encoding binary
|
|
||||||
set mdifffd($id) $mdf
|
|
||||||
set np [llength $parents($curview,$id)]
|
set np [llength $parents($curview,$id)]
|
||||||
set diffencoding [get_path_encoding {}]
|
|
||||||
settabs $np
|
settabs $np
|
||||||
filerun $mdf [list getmergediffline $mdf $id $np]
|
getblobdiffs $id
|
||||||
}
|
|
||||||
|
|
||||||
proc getmergediffline {mdf id np} {
|
|
||||||
global diffmergeid ctext cflist mergemax
|
|
||||||
global difffilestart mdifffd treediffs
|
|
||||||
global ctext_file_names ctext_file_lines
|
|
||||||
global diffencoding jump_to_here targetline diffline
|
|
||||||
|
|
||||||
$ctext conf -state normal
|
|
||||||
set nr 0
|
|
||||||
while {[incr nr] <= 1000 && [gets $mdf line] >= 0} {
|
|
||||||
if {![info exists diffmergeid] || $id != $diffmergeid
|
|
||||||
|| $mdf != $mdifffd($id)} {
|
|
||||||
close $mdf
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if {[regexp {^diff --cc (.*)} $line match fname]} {
|
|
||||||
# start of a new file
|
|
||||||
set fname [encoding convertfrom $fname]
|
|
||||||
$ctext insert end "\n"
|
|
||||||
set here [$ctext index "end - 1c"]
|
|
||||||
lappend difffilestart $here
|
|
||||||
lappend treediffs($id) $fname
|
|
||||||
add_flist [list $fname]
|
|
||||||
lappend ctext_file_names $fname
|
|
||||||
lappend ctext_file_lines [lindex [split $here "."] 0]
|
|
||||||
set diffencoding [get_path_encoding $fname]
|
|
||||||
set l [expr {(78 - [string length $fname]) / 2}]
|
|
||||||
set pad [string range "----------------------------------------" 1 $l]
|
|
||||||
$ctext insert end "$pad $fname $pad\n" filesep
|
|
||||||
set targetline {}
|
|
||||||
if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
|
|
||||||
set targetline [lindex $jump_to_here 1]
|
|
||||||
}
|
|
||||||
set diffline 0
|
|
||||||
} elseif {[regexp {^@@} $line]} {
|
|
||||||
set line [encoding convertfrom $diffencoding $line]
|
|
||||||
$ctext insert end "$line\n" hunksep
|
|
||||||
if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
|
|
||||||
set diffline $nl
|
|
||||||
}
|
|
||||||
} elseif {[regexp {^[0-9a-f]{40}$} $line] || [regexp {^index} $line]} {
|
|
||||||
# do nothing
|
|
||||||
} else {
|
|
||||||
set line [encoding convertfrom $diffencoding $line]
|
|
||||||
# parse the prefix - one ' ', '-' or '+' for each parent
|
|
||||||
set spaces {}
|
|
||||||
set minuses {}
|
|
||||||
set pluses {}
|
|
||||||
set isbad 0
|
|
||||||
for {set j 0} {$j < $np} {incr j} {
|
|
||||||
set c [string range $line $j $j]
|
|
||||||
if {$c == " "} {
|
|
||||||
lappend spaces $j
|
|
||||||
} elseif {$c == "-"} {
|
|
||||||
lappend minuses $j
|
|
||||||
} elseif {$c == "+"} {
|
|
||||||
lappend pluses $j
|
|
||||||
} else {
|
|
||||||
set isbad 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set tags {}
|
|
||||||
set num {}
|
|
||||||
if {!$isbad && $minuses ne {} && $pluses eq {}} {
|
|
||||||
# line doesn't appear in result, parents in $minuses have the line
|
|
||||||
set num [lindex $minuses 0]
|
|
||||||
} elseif {!$isbad && $pluses ne {} && $minuses eq {}} {
|
|
||||||
# line appears in result, parents in $pluses don't have the line
|
|
||||||
lappend tags mresult
|
|
||||||
set num [lindex $spaces 0]
|
|
||||||
}
|
|
||||||
if {$num ne {}} {
|
|
||||||
if {$num >= $mergemax} {
|
|
||||||
set num "max"
|
|
||||||
}
|
|
||||||
lappend tags m$num
|
|
||||||
}
|
|
||||||
$ctext insert end "$line\n" $tags
|
|
||||||
if {$targetline ne {} && $minuses eq {}} {
|
|
||||||
if {$diffline == $targetline} {
|
|
||||||
set here [$ctext index "end - 1 line"]
|
|
||||||
mark_ctext_line [lindex [split $here .] 0]
|
|
||||||
set targetline {}
|
|
||||||
} else {
|
|
||||||
incr diffline
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$ctext conf -state disabled
|
|
||||||
if {[eof $mdf]} {
|
|
||||||
close $mdf
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return [expr {$nr >= 1000? 2: 1}]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proc startdiff {ids} {
|
proc startdiff {ids} {
|
||||||
|
@ -6971,9 +6857,9 @@ proc getblobdiffs {ids} {
|
||||||
global diffcontext
|
global diffcontext
|
||||||
global ignorespace
|
global ignorespace
|
||||||
global limitdiffs vfilelimit curview
|
global limitdiffs vfilelimit curview
|
||||||
global diffencoding targetline
|
global diffencoding targetline diffnparents
|
||||||
|
|
||||||
set cmd [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"]
|
set cmd [diffcmd $ids "-p -C --cc --no-commit-id -U$diffcontext"]
|
||||||
if {$ignorespace} {
|
if {$ignorespace} {
|
||||||
append cmd " -w"
|
append cmd " -w"
|
||||||
}
|
}
|
||||||
|
@ -6981,10 +6867,11 @@ proc getblobdiffs {ids} {
|
||||||
set cmd [concat $cmd -- $vfilelimit($curview)]
|
set cmd [concat $cmd -- $vfilelimit($curview)]
|
||||||
}
|
}
|
||||||
if {[catch {set bdf [open $cmd r]} err]} {
|
if {[catch {set bdf [open $cmd r]} err]} {
|
||||||
puts "error getting diffs: $err"
|
error_popup [mc "Error getting diffs: %s" $err]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
set targetline {}
|
set targetline {}
|
||||||
|
set diffnparents 0
|
||||||
set diffinhdr 0
|
set diffinhdr 0
|
||||||
set diffencoding [get_path_encoding {}]
|
set diffencoding [get_path_encoding {}]
|
||||||
fconfigure $bdf -blocking 0 -encoding binary
|
fconfigure $bdf -blocking 0 -encoding binary
|
||||||
|
@ -7006,9 +6893,11 @@ proc setinlist {var i val} {
|
||||||
}
|
}
|
||||||
|
|
||||||
proc makediffhdr {fname ids} {
|
proc makediffhdr {fname ids} {
|
||||||
global ctext curdiffstart treediffs
|
global ctext curdiffstart treediffs diffencoding
|
||||||
global ctext_file_names jump_to_here targetline diffline
|
global ctext_file_names jump_to_here targetline diffline
|
||||||
|
|
||||||
|
set fname [encoding convertfrom $fname]
|
||||||
|
set diffencoding [get_path_encoding $fname]
|
||||||
set i [lsearch -exact $treediffs($ids) $fname]
|
set i [lsearch -exact $treediffs($ids) $fname]
|
||||||
if {$i >= 0} {
|
if {$i >= 0} {
|
||||||
setinlist difffilestart $i $curdiffstart
|
setinlist difffilestart $i $curdiffstart
|
||||||
|
@ -7028,7 +6917,7 @@ proc getblobdiffline {bdf ids} {
|
||||||
global diffids blobdifffd ctext curdiffstart
|
global diffids blobdifffd ctext curdiffstart
|
||||||
global diffnexthead diffnextnote difffilestart
|
global diffnexthead diffnextnote difffilestart
|
||||||
global ctext_file_names ctext_file_lines
|
global ctext_file_names ctext_file_lines
|
||||||
global diffinhdr treediffs
|
global diffinhdr treediffs mergemax diffnparents
|
||||||
global diffencoding jump_to_here targetline diffline
|
global diffencoding jump_to_here targetline diffline
|
||||||
|
|
||||||
set nr 0
|
set nr 0
|
||||||
|
@ -7038,47 +6927,63 @@ proc getblobdiffline {bdf ids} {
|
||||||
close $bdf
|
close $bdf
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if {![string compare -length 11 "diff --git " $line]} {
|
if {![string compare -length 5 "diff " $line]} {
|
||||||
# trim off "diff --git "
|
if {![regexp {^diff (--cc|--git) } $line m type]} {
|
||||||
set line [string range $line 11 end]
|
set line [encoding convertfrom $line]
|
||||||
set diffinhdr 1
|
$ctext insert end "$line\n" hunksep
|
||||||
|
continue
|
||||||
|
}
|
||||||
# start of a new file
|
# start of a new file
|
||||||
|
set diffinhdr 1
|
||||||
$ctext insert end "\n"
|
$ctext insert end "\n"
|
||||||
set curdiffstart [$ctext index "end - 1c"]
|
set curdiffstart [$ctext index "end - 1c"]
|
||||||
lappend ctext_file_names ""
|
lappend ctext_file_names ""
|
||||||
lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
|
lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
|
||||||
$ctext insert end "\n" filesep
|
$ctext insert end "\n" filesep
|
||||||
# If the name hasn't changed the length will be odd,
|
|
||||||
# the middle char will be a space, and the two bits either
|
if {$type eq "--cc"} {
|
||||||
# side will be a/name and b/name, or "a/name" and "b/name".
|
# start of a new file in a merge diff
|
||||||
# If the name has changed we'll get "rename from" and
|
set fname [string range $line 10 end]
|
||||||
# "rename to" or "copy from" and "copy to" lines following this,
|
if {[lsearch -exact $treediffs($ids) $fname] < 0} {
|
||||||
# and we'll use them to get the filenames.
|
lappend treediffs($ids) $fname
|
||||||
# This complexity is necessary because spaces in the filename(s)
|
add_flist [list $fname]
|
||||||
# don't get escaped.
|
}
|
||||||
set l [string length $line]
|
|
||||||
set i [expr {$l / 2}]
|
|
||||||
if {!(($l & 1) && [string index $line $i] eq " " &&
|
|
||||||
[string range $line 2 [expr {$i - 1}]] eq \
|
|
||||||
[string range $line [expr {$i + 3}] end])} {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
# unescape if quoted and chop off the a/ from the front
|
|
||||||
if {[string index $line 0] eq "\""} {
|
|
||||||
set fname [string range [lindex $line 0] 2 end]
|
|
||||||
} else {
|
} else {
|
||||||
set fname [string range $line 2 [expr {$i - 1}]]
|
set line [string range $line 11 end]
|
||||||
|
# If the name hasn't changed the length will be odd,
|
||||||
|
# the middle char will be a space, and the two bits either
|
||||||
|
# side will be a/name and b/name, or "a/name" and "b/name".
|
||||||
|
# If the name has changed we'll get "rename from" and
|
||||||
|
# "rename to" or "copy from" and "copy to" lines following
|
||||||
|
# this, and we'll use them to get the filenames.
|
||||||
|
# This complexity is necessary because spaces in the
|
||||||
|
# filename(s) don't get escaped.
|
||||||
|
set l [string length $line]
|
||||||
|
set i [expr {$l / 2}]
|
||||||
|
if {!(($l & 1) && [string index $line $i] eq " " &&
|
||||||
|
[string range $line 2 [expr {$i - 1}]] eq \
|
||||||
|
[string range $line [expr {$i + 3}] end])} {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
# unescape if quoted and chop off the a/ from the front
|
||||||
|
if {[string index $line 0] eq "\""} {
|
||||||
|
set fname [string range [lindex $line 0] 2 end]
|
||||||
|
} else {
|
||||||
|
set fname [string range $line 2 [expr {$i - 1}]]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
set fname [encoding convertfrom $fname]
|
|
||||||
set diffencoding [get_path_encoding $fname]
|
|
||||||
makediffhdr $fname $ids
|
makediffhdr $fname $ids
|
||||||
|
|
||||||
} elseif {[regexp {^@@ -([0-9]+)(,[0-9]+)? \+([0-9]+)(,[0-9]+)? @@(.*)} \
|
} elseif {![string compare -length 2 "@@" $line]} {
|
||||||
$line match f1l f1c f2l f2c rest]} {
|
regexp {^@@+} $line ats
|
||||||
set line [encoding convertfrom $diffencoding $line]
|
set line [encoding convertfrom $diffencoding $line]
|
||||||
$ctext insert end "$line\n" hunksep
|
$ctext insert end "$line\n" hunksep
|
||||||
|
if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
|
||||||
|
set diffline $nl
|
||||||
|
}
|
||||||
|
set diffnparents [expr {[string length $ats] - 1}]
|
||||||
set diffinhdr 0
|
set diffinhdr 0
|
||||||
set diffline $f2l
|
|
||||||
|
|
||||||
} elseif {$diffinhdr} {
|
} elseif {$diffinhdr} {
|
||||||
if {![string compare -length 12 "rename from " $line]} {
|
if {![string compare -length 12 "rename from " $line]} {
|
||||||
|
@ -7097,8 +7002,6 @@ proc getblobdiffline {bdf ids} {
|
||||||
if {[string index $fname 0] eq "\""} {
|
if {[string index $fname 0] eq "\""} {
|
||||||
set fname [lindex $fname 0]
|
set fname [lindex $fname 0]
|
||||||
}
|
}
|
||||||
set fname [encoding convertfrom $fname]
|
|
||||||
set diffencoding [get_path_encoding $fname]
|
|
||||||
makediffhdr $fname $ids
|
makediffhdr $fname $ids
|
||||||
} elseif {[string compare -length 3 $line "---"] == 0} {
|
} elseif {[string compare -length 3 $line "---"] == 0} {
|
||||||
# do nothing
|
# do nothing
|
||||||
|
@ -7111,28 +7014,53 @@ proc getblobdiffline {bdf ids} {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
set line [encoding convertfrom $diffencoding $line]
|
set line [encoding convertfrom $diffencoding $line]
|
||||||
set x [string range $line 0 0]
|
# parse the prefix - one ' ', '-' or '+' for each parent
|
||||||
set here [$ctext index "end - 1 chars"]
|
set prefix [string range $line 0 [expr {$diffnparents - 1}]]
|
||||||
if {$x == "-" || $x == "+"} {
|
set tag [expr {$diffnparents > 1? "m": "d"}]
|
||||||
set tag [expr {$x == "+"}]
|
if {[string trim $prefix " -+"] eq {}} {
|
||||||
$ctext insert end "$line\n" d$tag
|
# prefix only has " ", "-" and "+" in it: normal diff line
|
||||||
} elseif {$x == " "} {
|
set num [string first "-" $prefix]
|
||||||
$ctext insert end "$line\n"
|
if {$num >= 0} {
|
||||||
|
# removed line, first parent with line is $num
|
||||||
|
if {$num >= $mergemax} {
|
||||||
|
set num "max"
|
||||||
|
}
|
||||||
|
$ctext insert end "$line\n" $tag$num
|
||||||
|
} else {
|
||||||
|
set tags {}
|
||||||
|
if {[string first "+" $prefix] >= 0} {
|
||||||
|
# added line
|
||||||
|
lappend tags ${tag}result
|
||||||
|
if {$diffnparents > 1} {
|
||||||
|
set num [string first " " $prefix]
|
||||||
|
if {$num >= 0} {
|
||||||
|
if {$num >= $mergemax} {
|
||||||
|
set num "max"
|
||||||
|
}
|
||||||
|
lappend tags m$num
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if {$targetline ne {}} {
|
||||||
|
if {$diffline == $targetline} {
|
||||||
|
set seehere [$ctext index "end - 1 chars"]
|
||||||
|
set targetline {}
|
||||||
|
} else {
|
||||||
|
incr diffline
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ctext insert end "$line\n" $tags
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
# "\ No newline at end of file",
|
# "\ No newline at end of file",
|
||||||
# or something else we don't recognize
|
# or something else we don't recognize
|
||||||
$ctext insert end "$line\n" hunksep
|
$ctext insert end "$line\n" hunksep
|
||||||
}
|
}
|
||||||
if {$targetline ne {} && ($x eq " " || $x eq "+")} {
|
|
||||||
if {$diffline == $targetline} {
|
|
||||||
mark_ctext_line [lindex [split $here .] 0]
|
|
||||||
set targetline {}
|
|
||||||
} else {
|
|
||||||
incr diffline
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if {[info exists seehere]} {
|
||||||
|
mark_ctext_line [lindex [split $seehere .] 0]
|
||||||
|
}
|
||||||
$ctext conf -state disabled
|
$ctext conf -state disabled
|
||||||
if {[eof $bdf]} {
|
if {[eof $bdf]} {
|
||||||
close $bdf
|
close $bdf
|
||||||
|
@ -7145,7 +7073,7 @@ proc changediffdisp {} {
|
||||||
global ctext diffelide
|
global ctext diffelide
|
||||||
|
|
||||||
$ctext tag conf d0 -elide [lindex $diffelide 0]
|
$ctext tag conf d0 -elide [lindex $diffelide 0]
|
||||||
$ctext tag conf d1 -elide [lindex $diffelide 1]
|
$ctext tag conf dresult -elide [lindex $diffelide 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
proc highlightfile {loc cline} {
|
proc highlightfile {loc cline} {
|
||||||
|
@ -9817,7 +9745,7 @@ proc doprefs {} {
|
||||||
label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
|
label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
|
||||||
button $top.diffnewbut -text [mc "Diff: new lines"] -font optionfont \
|
button $top.diffnewbut -text [mc "Diff: new lines"] -font optionfont \
|
||||||
-command [list choosecolor diffcolors 1 $top.diffnew "diff new lines" \
|
-command [list choosecolor diffcolors 1 $top.diffnew "diff new lines" \
|
||||||
[list $ctext tag conf d1 -foreground]]
|
[list $ctext tag conf dresult -foreground]]
|
||||||
grid x $top.diffnewbut $top.diffnew -sticky w
|
grid x $top.diffnewbut $top.diffnew -sticky w
|
||||||
label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
|
label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
|
||||||
button $top.hunksepbut -text [mc "Diff: hunk header"] -font optionfont \
|
button $top.hunksepbut -text [mc "Diff: hunk header"] -font optionfont \
|
||||||
|
|
Loading…
Reference in New Issue