@matheusbsbs / matheus-bagliano / commits / 823f7cf81d
Fork 0

git-gui: Better positioning in Blame Parent Commit

Invoke diff-tree between the commit and its parent, and use the hunks to fix the target line number, accounting for addition and removal of lines. Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

Alexander Gavrilov committed Aug 23, 2008 at 12:31 UTC 823f7cf81dbed741c3a645913d7461e9bc04e0d2
1 file changed +61 -4
lib/blame.tcl
+61 -4
@@ -984,19 +984,76 @@ method _blameparent {} {
984 set dat [_get_click_amov_info $this]
985 if {$dat ne {}} {
986 set cmit [lindex $dat 0]
987 + set new_path [lindex $dat 1]
988
989 if {[catch {set cparent [git rev-parse --verify "$cmit^"]}]} {
990 error_popup [strcat [mc "Cannot find parent commit:"] "\n\n$err"]
991 return;
992 }
993
993 - _load_new_commit $this \
994 - $cparent \
995 - [lindex $dat 1] \
996 - [list [lindex $dat 2]]
994 + _kill $this
995 +
996 + # Generate a diff between the commit and its parent,
997 + # and use the hunks to update the line number.
998 + # Request zero context to simplify calculations.
999 + if {[catch {set fd [eval git_read diff-tree \
1000 + --unified=0 $cparent $cmit $new_path]} err]} {
1001 + $status stop [mc "Unable to display parent"]
1002 + error_popup [strcat [mc "Error loading diff:"] "\n\n$err"]
1003 + return
1004 + }
1005 +
1006 + set r_orig_line [lindex $dat 2]
1007 +
1008 + fconfigure $fd \
1009 + -blocking 0 \
1010 + -encoding binary \
1011 + -translation binary
1012 + fileevent $fd readable [cb _read_diff_load_commit \
1013 + $fd $cparent $new_path $r_orig_line]
1014 + set current_fd $fd
1015 }
1016 }
1017
1018 +method _read_diff_load_commit {fd cparent new_path tline} {
1019 + if {$fd ne $current_fd} {
1020 + catch {close $fd}
1021 + return
1022 + }
1023 +
1024 + while {[gets $fd line] >= 0} {
1025 + if {[regexp {^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@} $line line \
1026 + old_line osz old_size new_line nsz new_size]} {
1027 +
1028 + if {$osz eq {}} { set old_size 1 }
1029 + if {$nsz eq {}} { set new_size 1 }
1030 +
1031 + if {$new_line <= $tline} {
1032 + if {[expr {$new_line + $new_size}] > $tline} {
1033 + # Target line within the hunk
1034 + set line_shift [expr {
1035 + ($new_size-$old_size)*($tline-$new_line)/$new_size
1036 + }]
1037 + } else {
1038 + set line_shift [expr {$new_size-$old_size}]
1039 + }
1040 +
1041 + set r_orig_line [expr {$r_orig_line - $line_shift}]
1042 + }
1043 + }
1044 + }
1045 +
1046 + if {[eof $fd]} {
1047 + close $fd;
1048 + set current_fd {}
1049 +
1050 + _load_new_commit $this \
1051 + $cparent \
1052 + $new_path \
1053 + [list $r_orig_line]
1054 + }
1055 +} ifdeleted { catch {close $fd} }
1056 +
1057 method _show_tooltip {cur_w pos} {
1058 if {$tooltip_wm ne {}} {
1059 _open_tooltip $this $cur_w