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