gitk: Refactor per-line part of getblobdiffline and its support

For later use with data sources other than a pipe, refactor the big
worker part of getblobdiffline to a separate function
parseblobdiffline.  Also refactor its initialization and wrap-up to
separate routines.

Signed-off-by: Thomas Rast <trast@inf.ethz.ch>
Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Thomas Rast
2013-11-16 18:37:41 +01:00
committed by Paul Mackerras
parent 71846c5caf
commit 5de460a2cf

444
gitk
View File

@ -7752,15 +7752,25 @@ proc changeworddiff {name ix op} {
reselectline reselectline
} }
proc initblobdiffvars {} {
global diffencoding targetline diffnparents
global diffinhdr currdiffsubmod diffseehere
set targetline {}
set diffnparents 0
set diffinhdr 0
set diffencoding [get_path_encoding {}]
set currdiffsubmod ""
set diffseehere -1
}
proc getblobdiffs {ids} { proc getblobdiffs {ids} {
global blobdifffd diffids env global blobdifffd diffids env
global diffinhdr treediffs global treediffs
global diffcontext global diffcontext
global ignorespace global ignorespace
global worddiff global worddiff
global limitdiffs vfilelimit curview global limitdiffs vfilelimit curview
global diffencoding targetline diffnparents global git_version
global git_version currdiffsubmod
set textconv {} set textconv {}
if {[package vcompare $git_version "1.6.1"] >= 0} { if {[package vcompare $git_version "1.6.1"] >= 0} {
@ -7784,13 +7794,9 @@ proc getblobdiffs {ids} {
error_popup [mc "Error getting diffs: %s" $err] error_popup [mc "Error getting diffs: %s" $err]
return return
} }
set targetline {}
set diffnparents 0
set diffinhdr 0
set diffencoding [get_path_encoding {}]
fconfigure $bdf -blocking 0 -encoding binary -eofchar {} fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
set blobdifffd($ids) $bdf set blobdifffd($ids) $bdf
set currdiffsubmod "" initblobdiffvars
filerun $bdf [list getblobdiffline $bdf $diffids] filerun $bdf [list getblobdiffline $bdf $diffids]
} }
@ -7856,13 +7862,17 @@ proc makediffhdr {fname ids} {
set diffline 0 set diffline 0
} }
proc blobdiffmaybeseehere {ateof} {
global diffseehere
if {$diffseehere >= 0} {
mark_ctext_line [lindex [split $diffseehere .] 0]
}
maybe_scroll_ctext ateof
}
proc getblobdiffline {bdf ids} { proc getblobdiffline {bdf ids} {
global diffids blobdifffd ctext curdiffstart global diffids blobdifffd
global diffnexthead diffnextnote difffilestart global ctext
global ctext_file_names ctext_file_lines
global diffinhdr treediffs mergemax diffnparents
global diffencoding jump_to_here targetline diffline currdiffsubmod
global worddiff
set nr 0 set nr 0
$ctext conf -state normal $ctext conf -state normal
@ -7871,207 +7881,10 @@ proc getblobdiffline {bdf ids} {
catch {close $bdf} catch {close $bdf}
return 0 return 0
} }
if {![string compare -length 5 "diff " $line]} { parseblobdiffline $ids $line
if {![regexp {^diff (--cc|--git) } $line m type]} {
set line [encoding convertfrom $line]
$ctext insert end "$line\n" hunksep
continue
}
# start of a new file
set diffinhdr 1
$ctext insert end "\n"
set curdiffstart [$ctext index "end - 1c"]
lappend ctext_file_names ""
lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
$ctext insert end "\n" filesep
if {$type eq "--cc"} {
# start of a new file in a merge diff
set fname [string range $line 10 end]
if {[lsearch -exact $treediffs($ids) $fname] < 0} {
lappend treediffs($ids) $fname
add_flist [list $fname]
}
} else {
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}]]
}
}
makediffhdr $fname $ids
} elseif {![string compare -length 16 "* Unmerged path " $line]} {
set fname [encoding convertfrom [string range $line 16 end]]
$ctext insert end "\n"
set curdiffstart [$ctext index "end - 1c"]
lappend ctext_file_names $fname
lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
$ctext insert end "$line\n" filesep
set i [lsearch -exact $treediffs($ids) $fname]
if {$i >= 0} {
setinlist difffilestart $i $curdiffstart
}
} elseif {![string compare -length 2 "@@" $line]} {
regexp {^@@+} $line ats
set line [encoding convertfrom $diffencoding $line]
$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
} elseif {![string compare -length 10 "Submodule " $line]} {
# start of a new submodule
if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
} else {
set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
}
if {$currdiffsubmod != $fname} {
$ctext insert end "\n"; # Add newline after commit message
}
set curdiffstart [$ctext index "end - 1c"]
lappend ctext_file_names ""
if {$currdiffsubmod != $fname} {
lappend ctext_file_lines $fname
makediffhdr $fname $ids
set currdiffsubmod $fname
$ctext insert end "\n$line\n" filesep
} else {
$ctext insert end "$line\n" filesep
}
} elseif {![string compare -length 3 " >" $line]} {
set $currdiffsubmod ""
set line [encoding convertfrom $diffencoding $line]
$ctext insert end "$line\n" dresult
} elseif {![string compare -length 3 " <" $line]} {
set $currdiffsubmod ""
set line [encoding convertfrom $diffencoding $line]
$ctext insert end "$line\n" d0
} elseif {$diffinhdr} {
if {![string compare -length 12 "rename from " $line]} {
set fname [string range $line [expr 6 + [string first " from " $line] ] end]
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
set fname [encoding convertfrom $fname]
set i [lsearch -exact $treediffs($ids) $fname]
if {$i >= 0} {
setinlist difffilestart $i $curdiffstart
}
} elseif {![string compare -length 10 $line "rename to "] ||
![string compare -length 8 $line "copy to "]} {
set fname [string range $line [expr 4 + [string first " to " $line] ] end]
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
makediffhdr $fname $ids
} elseif {[string compare -length 3 $line "---"] == 0} {
# do nothing
continue
} elseif {[string compare -length 3 $line "+++"] == 0} {
set diffinhdr 0
continue
}
$ctext insert end "$line\n" filesep
} else {
set line [string map {\x1A ^Z} \
[encoding convertfrom $diffencoding $line]]
# parse the prefix - one ' ', '-' or '+' for each parent
set prefix [string range $line 0 [expr {$diffnparents - 1}]]
set tag [expr {$diffnparents > 1? "m": "d"}]
set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
set words_pre_markup ""
set words_post_markup ""
if {[string trim $prefix " -+"] eq {}} {
# prefix only has " ", "-" and "+" in it: normal diff line
set num [string first "-" $prefix]
if {$dowords} {
set line [string range $line 1 end]
}
if {$num >= 0} {
# removed line, first parent with line is $num
if {$num >= $mergemax} {
set num "max"
}
if {$dowords && $worddiff eq [mc "Markup words"]} {
$ctext insert end "\[-$line-\]" $tag$num
} else {
$ctext insert end "$line" $tag$num
}
if {!$dowords} {
$ctext insert end "\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
}
}
set words_pre_markup "{+"
set words_post_markup "+}"
}
if {$targetline ne {}} {
if {$diffline == $targetline} {
set seehere [$ctext index "end - 1 chars"]
set targetline {}
} else {
incr diffline
}
}
if {$dowords && $worddiff eq [mc "Markup words"]} {
$ctext insert end "$words_pre_markup$line$words_post_markup" $tags
} else {
$ctext insert end "$line" $tags
}
if {!$dowords} {
$ctext insert end "\n" $tags
}
}
} elseif {$dowords && $prefix eq "~"} {
$ctext insert end "\n" {}
} else {
# "\ No newline at end of file",
# or something else we don't recognize
$ctext insert end "$line\n" hunksep
}
}
} }
if {[info exists seehere]} {
mark_ctext_line [lindex [split $seehere .] 0]
}
maybe_scroll_ctext [eof $bdf]
$ctext conf -state disabled $ctext conf -state disabled
blobdiffmaybeseehere [eof $bdf]
if {[eof $bdf]} { if {[eof $bdf]} {
catch {close $bdf} catch {close $bdf}
return 0 return 0
@ -8079,6 +7892,211 @@ proc getblobdiffline {bdf ids} {
return [expr {$nr >= 1000? 2: 1}] return [expr {$nr >= 1000? 2: 1}]
} }
proc parseblobdiffline {ids line} {
global ctext curdiffstart
global diffnexthead diffnextnote difffilestart
global ctext_file_names ctext_file_lines
global diffinhdr treediffs mergemax diffnparents
global diffencoding jump_to_here targetline diffline currdiffsubmod
global worddiff diffseehere
if {![string compare -length 5 "diff " $line]} {
if {![regexp {^diff (--cc|--git) } $line m type]} {
set line [encoding convertfrom $line]
$ctext insert end "$line\n" hunksep
continue
}
# start of a new file
set diffinhdr 1
$ctext insert end "\n"
set curdiffstart [$ctext index "end - 1c"]
lappend ctext_file_names ""
lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
$ctext insert end "\n" filesep
if {$type eq "--cc"} {
# start of a new file in a merge diff
set fname [string range $line 10 end]
if {[lsearch -exact $treediffs($ids) $fname] < 0} {
lappend treediffs($ids) $fname
add_flist [list $fname]
}
} else {
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])} {
return
}
# 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}]]
}
}
makediffhdr $fname $ids
} elseif {![string compare -length 16 "* Unmerged path " $line]} {
set fname [encoding convertfrom [string range $line 16 end]]
$ctext insert end "\n"
set curdiffstart [$ctext index "end - 1c"]
lappend ctext_file_names $fname
lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
$ctext insert end "$line\n" filesep
set i [lsearch -exact $treediffs($ids) $fname]
if {$i >= 0} {
setinlist difffilestart $i $curdiffstart
}
} elseif {![string compare -length 2 "@@" $line]} {
regexp {^@@+} $line ats
set line [encoding convertfrom $diffencoding $line]
$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
} elseif {![string compare -length 10 "Submodule " $line]} {
# start of a new submodule
if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
} else {
set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
}
if {$currdiffsubmod != $fname} {
$ctext insert end "\n"; # Add newline after commit message
}
set curdiffstart [$ctext index "end - 1c"]
lappend ctext_file_names ""
if {$currdiffsubmod != $fname} {
lappend ctext_file_lines $fname
makediffhdr $fname $ids
set currdiffsubmod $fname
$ctext insert end "\n$line\n" filesep
} else {
$ctext insert end "$line\n" filesep
}
} elseif {![string compare -length 3 " >" $line]} {
set $currdiffsubmod ""
set line [encoding convertfrom $diffencoding $line]
$ctext insert end "$line\n" dresult
} elseif {![string compare -length 3 " <" $line]} {
set $currdiffsubmod ""
set line [encoding convertfrom $diffencoding $line]
$ctext insert end "$line\n" d0
} elseif {$diffinhdr} {
if {![string compare -length 12 "rename from " $line]} {
set fname [string range $line [expr 6 + [string first " from " $line] ] end]
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
set fname [encoding convertfrom $fname]
set i [lsearch -exact $treediffs($ids) $fname]
if {$i >= 0} {
setinlist difffilestart $i $curdiffstart
}
} elseif {![string compare -length 10 $line "rename to "] ||
![string compare -length 8 $line "copy to "]} {
set fname [string range $line [expr 4 + [string first " to " $line] ] end]
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
makediffhdr $fname $ids
} elseif {[string compare -length 3 $line "---"] == 0} {
# do nothing
return
} elseif {[string compare -length 3 $line "+++"] == 0} {
set diffinhdr 0
return
}
$ctext insert end "$line\n" filesep
} else {
set line [string map {\x1A ^Z} \
[encoding convertfrom $diffencoding $line]]
# parse the prefix - one ' ', '-' or '+' for each parent
set prefix [string range $line 0 [expr {$diffnparents - 1}]]
set tag [expr {$diffnparents > 1? "m": "d"}]
set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
set words_pre_markup ""
set words_post_markup ""
if {[string trim $prefix " -+"] eq {}} {
# prefix only has " ", "-" and "+" in it: normal diff line
set num [string first "-" $prefix]
if {$dowords} {
set line [string range $line 1 end]
}
if {$num >= 0} {
# removed line, first parent with line is $num
if {$num >= $mergemax} {
set num "max"
}
if {$dowords && $worddiff eq [mc "Markup words"]} {
$ctext insert end "\[-$line-\]" $tag$num
} else {
$ctext insert end "$line" $tag$num
}
if {!$dowords} {
$ctext insert end "\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
}
}
set words_pre_markup "{+"
set words_post_markup "+}"
}
if {$targetline ne {}} {
if {$diffline == $targetline} {
set diffseehere [$ctext index "end - 1 chars"]
set targetline {}
} else {
incr diffline
}
}
if {$dowords && $worddiff eq [mc "Markup words"]} {
$ctext insert end "$words_pre_markup$line$words_post_markup" $tags
} else {
$ctext insert end "$line" $tags
}
if {!$dowords} {
$ctext insert end "\n" $tags
}
}
} elseif {$dowords && $prefix eq "~"} {
$ctext insert end "\n" {}
} else {
# "\ No newline at end of file",
# or something else we don't recognize
$ctext insert end "$line\n" hunksep
}
}
}
proc changediffdisp {} { proc changediffdisp {} {
global ctext diffelide global ctext diffelide