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>

Thomas Rast committed Nov 16, 2013 at 18:37 UTC 5de460a2cfdd4acbadd41355a5b34dc69e93b89e
1 file changed +213 -195
gitk
+213 -195
@@ -7752,15 +7752,25 @@ proc changeworddiff {name ix op} {
7752 reselectline
7753 }
7754
7755 +proc initblobdiffvars {} {
7756 + global diffencoding targetline diffnparents
7757 + global diffinhdr currdiffsubmod diffseehere
7758 + set targetline {}
7759 + set diffnparents 0
7760 + set diffinhdr 0
7761 + set diffencoding [get_path_encoding {}]
7762 + set currdiffsubmod ""
7763 + set diffseehere -1
7764 +}
7765 +
7766 proc getblobdiffs {ids} {
7767 global blobdifffd diffids env
7757 - global diffinhdr treediffs
7768 + global treediffs
7769 global diffcontext
7770 global ignorespace
7771 global worddiff
7772 global limitdiffs vfilelimit curview
7762 - global diffencoding targetline diffnparents
7763 - global git_version currdiffsubmod
7773 + global git_version
7774
7775 set textconv {}
7776 if {[package vcompare $git_version "1.6.1"] >= 0} {
@@ -7784,13 +7794,9 @@ proc getblobdiffs {ids} {
7794 error_popup [mc "Error getting diffs: %s" $err]
7795 return
7796 }
7787 - set targetline {}
7788 - set diffnparents 0
7789 - set diffinhdr 0
7790 - set diffencoding [get_path_encoding {}]
7797 fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
7798 set blobdifffd($ids) $bdf
7793 - set currdiffsubmod ""
7799 + initblobdiffvars
7800 filerun $bdf [list getblobdiffline $bdf $diffids]
7801 }
7802
@@ -7856,13 +7862,17 @@ proc makediffhdr {fname ids} {
7862 set diffline 0
7863 }
7864
7865 +proc blobdiffmaybeseehere {ateof} {
7866 + global diffseehere
7867 + if {$diffseehere >= 0} {
7868 + mark_ctext_line [lindex [split $diffseehere .] 0]
7869 + }
7870 + maybe_scroll_ctext ateof
7871 +}
7872 +
7873 proc getblobdiffline {bdf ids} {
7860 - global diffids blobdifffd ctext curdiffstart
7861 - global diffnexthead diffnextnote difffilestart
7862 - global ctext_file_names ctext_file_lines
7863 - global diffinhdr treediffs mergemax diffnparents
7864 - global diffencoding jump_to_here targetline diffline currdiffsubmod
7865 - global worddiff
7874 + global diffids blobdifffd
7875 + global ctext
7876
7877 set nr 0
7878 $ctext conf -state normal
@@ -7871,212 +7881,220 @@ proc getblobdiffline {bdf ids} {
7881 catch {close $bdf}
7882 return 0
7883 }
7874 - if {![string compare -length 5 "diff " $line]} {
7875 - if {![regexp {^diff (--cc|--git) } $line m type]} {
7876 - set line [encoding convertfrom $line]
7877 - $ctext insert end "$line\n" hunksep
7878 - continue
7884 + parseblobdiffline $ids $line
7885 + }
7886 + $ctext conf -state disabled
7887 + blobdiffmaybeseehere [eof $bdf]
7888 + if {[eof $bdf]} {
7889 + catch {close $bdf}
7890 + return 0
7891 + }
7892 + return [expr {$nr >= 1000? 2: 1}]
7893 +}
7894 +
7895 +proc parseblobdiffline {ids line} {
7896 + global ctext curdiffstart
7897 + global diffnexthead diffnextnote difffilestart
7898 + global ctext_file_names ctext_file_lines
7899 + global diffinhdr treediffs mergemax diffnparents
7900 + global diffencoding jump_to_here targetline diffline currdiffsubmod
7901 + global worddiff diffseehere
7902 +
7903 + if {![string compare -length 5 "diff " $line]} {
7904 + if {![regexp {^diff (--cc|--git) } $line m type]} {
7905 + set line [encoding convertfrom $line]
7906 + $ctext insert end "$line\n" hunksep
7907 + continue
7908 + }
7909 + # start of a new file
7910 + set diffinhdr 1
7911 + $ctext insert end "\n"
7912 + set curdiffstart [$ctext index "end - 1c"]
7913 + lappend ctext_file_names ""
7914 + lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
7915 + $ctext insert end "\n" filesep
7916 +
7917 + if {$type eq "--cc"} {
7918 + # start of a new file in a merge diff
7919 + set fname [string range $line 10 end]
7920 + if {[lsearch -exact $treediffs($ids) $fname] < 0} {
7921 + lappend treediffs($ids) $fname
7922 + add_flist [list $fname]
7923 }
7880 - # start of a new file
7881 - set diffinhdr 1
7882 - $ctext insert end "\n"
7883 - set curdiffstart [$ctext index "end - 1c"]
7884 - lappend ctext_file_names ""
7885 - lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
7886 - $ctext insert end "\n" filesep
7887 -
7888 - if {$type eq "--cc"} {
7889 - # start of a new file in a merge diff
7890 - set fname [string range $line 10 end]
7891 - if {[lsearch -exact $treediffs($ids) $fname] < 0} {
7892 - lappend treediffs($ids) $fname
7893 - add_flist [list $fname]
7894 - }
7924
7925 + } else {
7926 + set line [string range $line 11 end]
7927 + # If the name hasn't changed the length will be odd,
7928 + # the middle char will be a space, and the two bits either
7929 + # side will be a/name and b/name, or "a/name" and "b/name".
7930 + # If the name has changed we'll get "rename from" and
7931 + # "rename to" or "copy from" and "copy to" lines following
7932 + # this, and we'll use them to get the filenames.
7933 + # This complexity is necessary because spaces in the
7934 + # filename(s) don't get escaped.
7935 + set l [string length $line]
7936 + set i [expr {$l / 2}]
7937 + if {!(($l & 1) && [string index $line $i] eq " " &&
7938 + [string range $line 2 [expr {$i - 1}]] eq \
7939 + [string range $line [expr {$i + 3}] end])} {
7940 + return
7941 + }
7942 + # unescape if quoted and chop off the a/ from the front
7943 + if {[string index $line 0] eq "\""} {
7944 + set fname [string range [lindex $line 0] 2 end]
7945 } else {
7897 - set line [string range $line 11 end]
7898 - # If the name hasn't changed the length will be odd,
7899 - # the middle char will be a space, and the two bits either
7900 - # side will be a/name and b/name, or "a/name" and "b/name".
7901 - # If the name has changed we'll get "rename from" and
7902 - # "rename to" or "copy from" and "copy to" lines following
7903 - # this, and we'll use them to get the filenames.
7904 - # This complexity is necessary because spaces in the
7905 - # filename(s) don't get escaped.
7906 - set l [string length $line]
7907 - set i [expr {$l / 2}]
7908 - if {!(($l & 1) && [string index $line $i] eq " " &&
7909 - [string range $line 2 [expr {$i - 1}]] eq \
7910 - [string range $line [expr {$i + 3}] end])} {
7911 - continue
7912 - }
7913 - # unescape if quoted and chop off the a/ from the front
7914 - if {[string index $line 0] eq "\""} {
7915 - set fname [string range [lindex $line 0] 2 end]
7916 - } else {
7917 - set fname [string range $line 2 [expr {$i - 1}]]
7918 - }
7946 + set fname [string range $line 2 [expr {$i - 1}]]
7947 }
7920 - makediffhdr $fname $ids
7948 + }
7949 + makediffhdr $fname $ids
7950
7922 - } elseif {![string compare -length 16 "* Unmerged path " $line]} {
7923 - set fname [encoding convertfrom [string range $line 16 end]]
7924 - $ctext insert end "\n"
7925 - set curdiffstart [$ctext index "end - 1c"]
7926 - lappend ctext_file_names $fname
7927 - lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
7951 + } elseif {![string compare -length 16 "* Unmerged path " $line]} {
7952 + set fname [encoding convertfrom [string range $line 16 end]]
7953 + $ctext insert end "\n"
7954 + set curdiffstart [$ctext index "end - 1c"]
7955 + lappend ctext_file_names $fname
7956 + lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
7957 + $ctext insert end "$line\n" filesep
7958 + set i [lsearch -exact $treediffs($ids) $fname]
7959 + if {$i >= 0} {
7960 + setinlist difffilestart $i $curdiffstart
7961 + }
7962 +
7963 + } elseif {![string compare -length 2 "@@" $line]} {
7964 + regexp {^@@+} $line ats
7965 + set line [encoding convertfrom $diffencoding $line]
7966 + $ctext insert end "$line\n" hunksep
7967 + if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
7968 + set diffline $nl
7969 + }
7970 + set diffnparents [expr {[string length $ats] - 1}]
7971 + set diffinhdr 0
7972 +
7973 + } elseif {![string compare -length 10 "Submodule " $line]} {
7974 + # start of a new submodule
7975 + if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
7976 + set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
7977 + } else {
7978 + set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
7979 + }
7980 + if {$currdiffsubmod != $fname} {
7981 + $ctext insert end "\n"; # Add newline after commit message
7982 + }
7983 + set curdiffstart [$ctext index "end - 1c"]
7984 + lappend ctext_file_names ""
7985 + if {$currdiffsubmod != $fname} {
7986 + lappend ctext_file_lines $fname
7987 + makediffhdr $fname $ids
7988 + set currdiffsubmod $fname
7989 + $ctext insert end "\n$line\n" filesep
7990 + } else {
7991 $ctext insert end "$line\n" filesep
7992 + }
7993 + } elseif {![string compare -length 3 " >" $line]} {
7994 + set $currdiffsubmod ""
7995 + set line [encoding convertfrom $diffencoding $line]
7996 + $ctext insert end "$line\n" dresult
7997 + } elseif {![string compare -length 3 " <" $line]} {
7998 + set $currdiffsubmod ""
7999 + set line [encoding convertfrom $diffencoding $line]
8000 + $ctext insert end "$line\n" d0
8001 + } elseif {$diffinhdr} {
8002 + if {![string compare -length 12 "rename from " $line]} {
8003 + set fname [string range $line [expr 6 + [string first " from " $line] ] end]
8004 + if {[string index $fname 0] eq "\""} {
8005 + set fname [lindex $fname 0]
8006 + }
8007 + set fname [encoding convertfrom $fname]
8008 set i [lsearch -exact $treediffs($ids) $fname]
8009 if {$i >= 0} {
8010 setinlist difffilestart $i $curdiffstart
8011 }
7933 -
7934 - } elseif {![string compare -length 2 "@@" $line]} {
7935 - regexp {^@@+} $line ats
7936 - set line [encoding convertfrom $diffencoding $line]
7937 - $ctext insert end "$line\n" hunksep
7938 - if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
7939 - set diffline $nl
8012 + } elseif {![string compare -length 10 $line "rename to "] ||
8013 + ![string compare -length 8 $line "copy to "]} {
8014 + set fname [string range $line [expr 4 + [string first " to " $line] ] end]
8015 + if {[string index $fname 0] eq "\""} {
8016 + set fname [lindex $fname 0]
8017 }
7941 - set diffnparents [expr {[string length $ats] - 1}]
8018 + makediffhdr $fname $ids
8019 + } elseif {[string compare -length 3 $line "---"] == 0} {
8020 + # do nothing
8021 + return
8022 + } elseif {[string compare -length 3 $line "+++"] == 0} {
8023 set diffinhdr 0
8024 + return
8025 + }
8026 + $ctext insert end "$line\n" filesep
8027
7944 - } elseif {![string compare -length 10 "Submodule " $line]} {
7945 - # start of a new submodule
7946 - if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
7947 - set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
7948 - } else {
7949 - set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
7950 - }
7951 - if {$currdiffsubmod != $fname} {
7952 - $ctext insert end "\n"; # Add newline after commit message
7953 - }
7954 - set curdiffstart [$ctext index "end - 1c"]
7955 - lappend ctext_file_names ""
7956 - if {$currdiffsubmod != $fname} {
7957 - lappend ctext_file_lines $fname
7958 - makediffhdr $fname $ids
7959 - set currdiffsubmod $fname
7960 - $ctext insert end "\n$line\n" filesep
7961 - } else {
7962 - $ctext insert end "$line\n" filesep
7963 - }
7964 - } elseif {![string compare -length 3 " >" $line]} {
7965 - set $currdiffsubmod ""
7966 - set line [encoding convertfrom $diffencoding $line]
7967 - $ctext insert end "$line\n" dresult
7968 - } elseif {![string compare -length 3 " <" $line]} {
7969 - set $currdiffsubmod ""
7970 - set line [encoding convertfrom $diffencoding $line]
7971 - $ctext insert end "$line\n" d0
7972 - } elseif {$diffinhdr} {
7973 - if {![string compare -length 12 "rename from " $line]} {
7974 - set fname [string range $line [expr 6 + [string first " from " $line] ] end]
7975 - if {[string index $fname 0] eq "\""} {
7976 - set fname [lindex $fname 0]
7977 - }
7978 - set fname [encoding convertfrom $fname]
7979 - set i [lsearch -exact $treediffs($ids) $fname]
7980 - if {$i >= 0} {
7981 - setinlist difffilestart $i $curdiffstart
8028 + } else {
8029 + set line [string map {\x1A ^Z} \
8030 + [encoding convertfrom $diffencoding $line]]
8031 + # parse the prefix - one ' ', '-' or '+' for each parent
8032 + set prefix [string range $line 0 [expr {$diffnparents - 1}]]
8033 + set tag [expr {$diffnparents > 1? "m": "d"}]
8034 + set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
8035 + set words_pre_markup ""
8036 + set words_post_markup ""
8037 + if {[string trim $prefix " -+"] eq {}} {
8038 + # prefix only has " ", "-" and "+" in it: normal diff line
8039 + set num [string first "-" $prefix]
8040 + if {$dowords} {
8041 + set line [string range $line 1 end]
8042 + }
8043 + if {$num >= 0} {
8044 + # removed line, first parent with line is $num
8045 + if {$num >= $mergemax} {
8046 + set num "max"
8047 }
7983 - } elseif {![string compare -length 10 $line "rename to "] ||
7984 - ![string compare -length 8 $line "copy to "]} {
7985 - set fname [string range $line [expr 4 + [string first " to " $line] ] end]
7986 - if {[string index $fname 0] eq "\""} {
7987 - set fname [lindex $fname 0]
8048 + if {$dowords && $worddiff eq [mc "Markup words"]} {
8049 + $ctext insert end "\[-$line-\]" $tag$num
8050 + } else {
8051 + $ctext insert end "$line" $tag$num
8052 }
7989 - makediffhdr $fname $ids
7990 - } elseif {[string compare -length 3 $line "---"] == 0} {
7991 - # do nothing
7992 - continue
7993 - } elseif {[string compare -length 3 $line "+++"] == 0} {
7994 - set diffinhdr 0
7995 - continue
7996 - }
7997 - $ctext insert end "$line\n" filesep
7998 -
7999 - } else {
8000 - set line [string map {\x1A ^Z} \
8001 - [encoding convertfrom $diffencoding $line]]
8002 - # parse the prefix - one ' ', '-' or '+' for each parent
8003 - set prefix [string range $line 0 [expr {$diffnparents - 1}]]
8004 - set tag [expr {$diffnparents > 1? "m": "d"}]
8005 - set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
8006 - set words_pre_markup ""
8007 - set words_post_markup ""
8008 - if {[string trim $prefix " -+"] eq {}} {
8009 - # prefix only has " ", "-" and "+" in it: normal diff line
8010 - set num [string first "-" $prefix]
8011 - if {$dowords} {
8012 - set line [string range $line 1 end]
8053 + if {!$dowords} {
8054 + $ctext insert end "\n" $tag$num
8055 }
8014 - if {$num >= 0} {
8015 - # removed line, first parent with line is $num
8016 - if {$num >= $mergemax} {
8017 - set num "max"
8018 - }
8019 - if {$dowords && $worddiff eq [mc "Markup words"]} {
8020 - $ctext insert end "\[-$line-\]" $tag$num
8021 - } else {
8022 - $ctext insert end "$line" $tag$num
8023 - }
8024 - if {!$dowords} {
8025 - $ctext insert end "\n" $tag$num
8026 - }
8027 - } else {
8028 - set tags {}
8029 - if {[string first "+" $prefix] >= 0} {
8030 - # added line
8031 - lappend tags ${tag}result
8032 - if {$diffnparents > 1} {
8033 - set num [string first " " $prefix]
8034 - if {$num >= 0} {
8035 - if {$num >= $mergemax} {
8036 - set num "max"
8037 - }
8038 - lappend tags m$num
8056 + } else {
8057 + set tags {}
8058 + if {[string first "+" $prefix] >= 0} {
8059 + # added line
8060 + lappend tags ${tag}result
8061 + if {$diffnparents > 1} {
8062 + set num [string first " " $prefix]
8063 + if {$num >= 0} {
8064 + if {$num >= $mergemax} {
8065 + set num "max"
8066 }
8067 + lappend tags m$num
8068 }
8041 - set words_pre_markup "{+"
8042 - set words_post_markup "+}"
8069 }
8044 - if {$targetline ne {}} {
8045 - if {$diffline == $targetline} {
8046 - set seehere [$ctext index "end - 1 chars"]
8047 - set targetline {}
8048 - } else {
8049 - incr diffline
8050 - }
8051 - }
8052 - if {$dowords && $worddiff eq [mc "Markup words"]} {
8053 - $ctext insert end "$words_pre_markup$line$words_post_markup" $tags
8070 + set words_pre_markup "{+"
8071 + set words_post_markup "+}"
8072 + }
8073 + if {$targetline ne {}} {
8074 + if {$diffline == $targetline} {
8075 + set diffseehere [$ctext index "end - 1 chars"]
8076 + set targetline {}
8077 } else {
8055 - $ctext insert end "$line" $tags
8056 - }
8057 - if {!$dowords} {
8058 - $ctext insert end "\n" $tags
8078 + incr diffline
8079 }
8080 }
8061 - } elseif {$dowords && $prefix eq "~"} {
8062 - $ctext insert end "\n" {}
8063 - } else {
8064 - # "\ No newline at end of file",
8065 - # or something else we don't recognize
8066 - $ctext insert end "$line\n" hunksep
8081 + if {$dowords && $worddiff eq [mc "Markup words"]} {
8082 + $ctext insert end "$words_pre_markup$line$words_post_markup" $tags
8083 + } else {
8084 + $ctext insert end "$line" $tags
8085 + }
8086 + if {!$dowords} {
8087 + $ctext insert end "\n" $tags
8088 + }
8089 }
8090 + } elseif {$dowords && $prefix eq "~"} {
8091 + $ctext insert end "\n" {}
8092 + } else {
8093 + # "\ No newline at end of file",
8094 + # or something else we don't recognize
8095 + $ctext insert end "$line\n" hunksep
8096 }
8097 }
8070 - if {[info exists seehere]} {
8071 - mark_ctext_line [lindex [split $seehere .] 0]
8072 - }
8073 - maybe_scroll_ctext [eof $bdf]
8074 - $ctext conf -state disabled
8075 - if {[eof $bdf]} {
8076 - catch {close $bdf}
8077 - return 0
8078 - }
8079 - return [expr {$nr >= 1000? 2: 1}]
8098 }
8099
8100 proc changediffdisp {} {