@matheusbsbs / matheus-bagliano / commits / fc4977e1b9
Fork 0

gitk: Make "show origin of this line" work on fake commits

This makes the "Show origin of this line" menu item work correctly on the fake commits that gitk shows for local uncommitted changes. With the fake commit for changes that aren't checked in to the index, we can actually get a 3-way diff shown, which means we might have to blame either the parent or the commit being merged in (which we get from .git/MERGE_HEAD). If the parent is the fake commit which shows the changes that have been checked in to the index, then we need to get the SHA1 of the blob for the version of the file that is in the index, then use git cat-file blob to get the contents of the blob, and give that to git blame with --contents - so that git blame will do the blame on the index version of the file. In that case, we might get the all-zeroes SHA1 back from git blame, meaning that the line is new in the index version of the file, so then we have to use $nullid2 (the pseudo-SHA1 of the fake commit for the checked-in changes). Signed-off-by: Paul Mackerras <paulus@samba.org>

Paul Mackerras committed Nov 4, 2008 at 12:57 UTC fc4977e1b989503c6dcfbc527cda2458d63d0400
1 file changed +61 -3
gitk
+61 -3
@@ -3238,6 +3238,22 @@ proc external_blame_diff {} {
3238 external_blame $parent_idx $line
3239 }
3240
3241 +# Find the SHA1 ID of the blob for file $fname in the index
3242 +# at stage 0 or 2
3243 +proc index_sha1 {fname} {
3244 + set f [open [list | git ls-files -s $fname] r]
3245 + while {[gets $f line] >= 0} {
3246 + set info [lindex [split $line "\t"] 0]
3247 + set stage [lindex $info 2]
3248 + if {$stage eq "0" || $stage eq "2"} {
3249 + close $f
3250 + return [lindex $info 1]
3251 + }
3252 + }
3253 + close $f
3254 + return {}
3255 +}
3256 +
3257 proc external_blame {parent_idx {line {}}} {
3258 global flist_menu_file
3259 global nullid nullid2
@@ -3267,7 +3283,9 @@ proc external_blame {parent_idx {line {}}} {
3283 proc show_line_source {} {
3284 global cmitmode currentid parents curview blamestuff blameinst
3285 global diff_menu_line diff_menu_filebase flist_menu_file
3286 + global nullid nullid2 gitdir
3287
3288 + set from_index {}
3289 if {$cmitmode eq "tree"} {
3290 set id $currentid
3291 set line [expr {$diff_menu_line - $diff_menu_filebase}]
@@ -3279,11 +3297,46 @@ proc show_line_source {} {
3297 mark_ctext_line $diff_menu_line
3298 return
3299 }
3282 - set id [lindex $parents($curview,$currentid) [expr {$pi - 1}]]
3300 + incr pi -1
3301 + if {$currentid eq $nullid} {
3302 + if {$pi > 0} {
3303 + # must be a merge in progress...
3304 + if {[catch {
3305 + # get the last line from .git/MERGE_HEAD
3306 + set f [open [file join $gitdir MERGE_HEAD] r]
3307 + set id [lindex [split [read $f] "\n"] end-1]
3308 + close $f
3309 + } err]} {
3310 + error_popup [mc "Couldn't read merge head: %s" $err]
3311 + return
3312 + }
3313 + } elseif {$parents($curview,$currentid) eq $nullid2} {
3314 + # need to do the blame from the index
3315 + if {[catch {
3316 + set from_index [index_sha1 $flist_menu_file]
3317 + } err]} {
3318 + error_popup [mc "Error reading index: %s" $err]
3319 + return
3320 + }
3321 + }
3322 + } else {
3323 + set id [lindex $parents($curview,$currentid) $pi]
3324 + }
3325 set line [lindex $h 1]
3326 }
3327 + set blameargs {}
3328 + if {$from_index ne {}} {
3329 + lappend blameargs | git cat-file blob $from_index
3330 + }
3331 + lappend blameargs | git blame -p -L$line,+1
3332 + if {$from_index ne {}} {
3333 + lappend blameargs --contents -
3334 + } else {
3335 + lappend blameargs $id
3336 + }
3337 + lappend blameargs -- $flist_menu_file
3338 if {[catch {
3286 - set f [open [list | git blame -p -L$line,+1 $id -- $flist_menu_file] r]
3339 + set f [open $blameargs r]
3340 } err]} {
3341 error_popup [mc "Couldn't start git blame: %s" $err]
3342 return
@@ -3305,7 +3358,7 @@ proc stopblaming {} {
3358 }
3359
3360 proc read_line_source {fd inst} {
3308 - global blamestuff curview commfd blameinst
3361 + global blamestuff curview commfd blameinst nullid nullid2
3362
3363 while {[gets $fd line] >= 0} {
3364 lappend blamestuff($inst) $line
@@ -3337,6 +3390,11 @@ proc read_line_source {fd inst} {
3390 }
3391 if {$fname ne {}} {
3392 # all looks good, select it
3393 + if {$id eq $nullid} {
3394 + # blame uses all-zeroes to mean not committed,
3395 + # which would mean a change in the index
3396 + set id $nullid2
3397 + }
3398 if {[commitinview $id $curview]} {
3399 selectline [rowofcommit $id] 1 [list $fname $lnum]
3400 } else {