On Mon, Feb 3, 2014 at 5:41 PM, Max Kirillov <max@xxxxxxxxxx> wrote: > 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{}, s/parsin/parsing/ s/in the/in/ > but returns only information for a single line. s/but/but it/ > 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 <max@xxxxxxxxxx> > --- > 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 majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html