aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlexander Gavrilov <angavrilov@gmail.com>2008-08-23 12:31:35 +0400
committerShawn O. Pearce <spearce@spearce.org>2008-08-24 22:00:01 -0700
commit823f7cf81dbed741c3a645913d7461e9bc04e0d2 (patch)
treed70765509a50406391c5aab38b551d0dcab6cbe0 /lib
parent80fd76bd58070fe9615baf365abf2ff82276e50c (diff)
downloadgit-823f7cf81dbed741c3a645913d7461e9bc04e0d2.tar.gz
git-823f7cf81dbed741c3a645913d7461e9bc04e0d2.tar.xz
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>
Diffstat (limited to 'lib')
-rw-r--r--lib/blame.tcl65
1 files changed, 61 insertions, 4 deletions
diff --git a/lib/blame.tcl b/lib/blame.tcl
index ef4223179..110697577 100644
--- a/lib/blame.tcl
+++ b/lib/blame.tcl
@@ -984,19 +984,76 @@ method _blameparent {} {
set dat [_get_click_amov_info $this]
if {$dat ne {}} {
set cmit [lindex $dat 0]
+ set new_path [lindex $dat 1]
if {[catch {set cparent [git rev-parse --verify "$cmit^"]}]} {
error_popup [strcat [mc "Cannot find parent commit:"] "\n\n$err"]
return;
}
- _load_new_commit $this \
- $cparent \
- [lindex $dat 1] \
- [list [lindex $dat 2]]
+ _kill $this
+
+ # Generate a diff between the commit and its parent,
+ # and use the hunks to update the line number.
+ # Request zero context to simplify calculations.
+ if {[catch {set fd [eval git_read diff-tree \
+ --unified=0 $cparent $cmit $new_path]} err]} {
+ $status stop [mc "Unable to display parent"]
+ error_popup [strcat [mc "Error loading diff:"] "\n\n$err"]
+ return
+ }
+
+ set r_orig_line [lindex $dat 2]
+
+ fconfigure $fd \
+ -blocking 0 \
+ -encoding binary \
+ -translation binary
+ fileevent $fd readable [cb _read_diff_load_commit \
+ $fd $cparent $new_path $r_orig_line]
+ set current_fd $fd
}
}
+method _read_diff_load_commit {fd cparent new_path tline} {
+ if {$fd ne $current_fd} {
+ catch {close $fd}
+ return
+ }
+
+ while {[gets $fd line] >= 0} {
+ if {[regexp {^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@} $line line \
+ old_line osz old_size new_line nsz new_size]} {
+
+ if {$osz eq {}} { set old_size 1 }
+ if {$nsz eq {}} { set new_size 1 }
+
+ if {$new_line <= $tline} {
+ if {[expr {$new_line + $new_size}] > $tline} {
+ # Target line within the hunk
+ set line_shift [expr {
+ ($new_size-$old_size)*($tline-$new_line)/$new_size
+ }]
+ } else {
+ set line_shift [expr {$new_size-$old_size}]
+ }
+
+ set r_orig_line [expr {$r_orig_line - $line_shift}]
+ }
+ }
+ }
+
+ if {[eof $fd]} {
+ close $fd;
+ set current_fd {}
+
+ _load_new_commit $this \
+ $cparent \
+ $new_path \
+ [list $r_orig_line]
+ }
+} ifdeleted { catch {close $fd} }
+
method _show_tooltip {cur_w pos} {
if {$tooltip_wm ne {}} {
_open_tooltip $this $cur_w