For requesting a region blame, it is necessary to parse a hunk and
find the region in the parent file corresponding to the selected region.
There is already hunk parsin functionality in the find_hunk_blamespec{},
but returns only information for a single line.
The new function, resolve_hunk_lines{}, scans the hunk once and returns
for all hunk lines between $start_diffline and $end_diffline, in which parent
each of them exists and which is its number there.
Signed-off-by: Max Kirillov <[email protected]>
---
gitk | 93 ++++++++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 57 insertions(+), 36 deletions(-)
diff --git a/gitk b/gitk
index dfac4fd..7699a66 100755
--- a/gitk
+++ b/gitk
@@ -3590,11 +3590,11 @@ proc external_diff {} {
}
}
-proc find_hunk_blamespec {base line} {
+proc resolve_hunk_lines {base start_diffline end_diffline} {
global ctext
# Find and parse the hunk header
- set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
+ set s_lix [$ctext search -backwards -regexp ^@@ "$start_diffline.0
lineend" $base.0]
if {$s_lix eq {}} return
set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
@@ -3614,49 +3614,70 @@ proc find_hunk_blamespec {base line} {
}
# Now scan the lines to determine offset within the hunk
- set max_parent [expr {[llength $base_lines]-2}]
- set dline 0
+ set max_parent [expr {[llength $base_lines]-1}]
set s_lno [lindex [split $s_lix "."] 0]
- # Determine if the line is removed
- set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
- if {[string match {[-+ ]*} $chunk]} {
- set removed_idx [string first "-" $chunk]
- # Choose a parent index
- if {$removed_idx >= 0} {
- set parent $removed_idx
+ set commitlines_by_diffline {}
+ array unset commit_lines
+ for {set p 0} {$p <= $max_parent} {incr p} {
+ set commit_lines($p) [expr [lindex $base_lines $p] - 1]
+ }
+ for {set diffline [expr $s_lno + 1]} {$diffline <= $end_diffline} {incr
diffline} {
+ set chunk [$ctext get $diffline.0 "$diffline.0 + $max_parent chars"]
+ if {$chunk eq {} || [string match "\[\n@\]*" $chunk]} {
+ # region is larger than hunk
+ return {}
+ }
+ set is_removed [expr [string first "-" $chunk] >= 0]
+ if {!$is_removed} {
+ incr commit_lines(0)
+ set commitlines [list [list 0 $commit_lines(0)]]
} else {
- set unchanged_idx [string first " " $chunk]
- if {$unchanged_idx >= 0} {
- set parent $unchanged_idx
- } else {
- # blame the current commit
- set parent -1
- }
- }
- # then count other lines that belong to it
- for {set i $line} {[incr i -1] > $s_lno} {} {
- set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
- # Determine if the line is removed
- set removed_idx [string first "-" $chunk]
- if {$parent >= 0} {
- set code [string index $chunk $parent]
- if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
- incr dline
+ set commitlines {}
+ }
+ for {set p 1} {$p <= $max_parent} {incr p} {
+ switch -- [string index $chunk "$p-1"] {
+ "+" {
}
- } else {
- if {$removed_idx < 0} {
- incr dline
+ "-" {
+ incr commit_lines($p)
+ lappend commitlines [list $p $commit_lines($p)]
+ }
+ " " {
+ if {!$is_removed} {
+ incr commit_lines($p)
+ lappend commitlines [list $p $commit_lines($p)]
+ }
+ }
+ default {
+ error_popup "resolve_hunk_lines: unexpected diff
line($diffline): $chunk"
+ break
}
}
}
- incr parent
- } else {
- set parent 0
+ if {$diffline >= $start_diffline} {
+ lappend commitlines_by_diffline [list $diffline $commitlines]
+ }
}
+ return $commitlines_by_diffline
+}
- incr dline [lindex $base_lines $parent]
- return [list $parent $dline]
+proc find_hunk_blamespec {base line} {
+ foreach cl_spec [resolve_hunk_lines $base $line $line] {
+ if {[lindex $cl_spec 0] == $line} {
+ set commitlines [lindex $cl_spec 1]
+ if {[llength $commitlines] > 0} {
+ if {[llength $commitlines] > 1 && [lindex $commitlines 0 0] eq
0} {
+ return [lindex $commitlines 1]
+ } else {
+ return [lindex $commitlines 0]
+ }
+ } else {
+ error_popup "find_hunk_blamespec: invalid commitlines:
$commitlines"
+ }
+ }
+ }
+ return {}
}
proc external_blame_diff {} {
--
1.8.5.2.421.g4cdf8d0
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html