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>
This commit is contained in:
parent
8b07dca18a
commit
fc4977e1b9
64
gitk
64
gitk
@ -3238,6 +3238,22 @@ proc external_blame_diff {} {
|
|||||||
external_blame $parent_idx $line
|
external_blame $parent_idx $line
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Find the SHA1 ID of the blob for file $fname in the index
|
||||||
|
# at stage 0 or 2
|
||||||
|
proc index_sha1 {fname} {
|
||||||
|
set f [open [list | git ls-files -s $fname] r]
|
||||||
|
while {[gets $f line] >= 0} {
|
||||||
|
set info [lindex [split $line "\t"] 0]
|
||||||
|
set stage [lindex $info 2]
|
||||||
|
if {$stage eq "0" || $stage eq "2"} {
|
||||||
|
close $f
|
||||||
|
return [lindex $info 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close $f
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
proc external_blame {parent_idx {line {}}} {
|
proc external_blame {parent_idx {line {}}} {
|
||||||
global flist_menu_file
|
global flist_menu_file
|
||||||
global nullid nullid2
|
global nullid nullid2
|
||||||
@ -3267,7 +3283,9 @@ proc external_blame {parent_idx {line {}}} {
|
|||||||
proc show_line_source {} {
|
proc show_line_source {} {
|
||||||
global cmitmode currentid parents curview blamestuff blameinst
|
global cmitmode currentid parents curview blamestuff blameinst
|
||||||
global diff_menu_line diff_menu_filebase flist_menu_file
|
global diff_menu_line diff_menu_filebase flist_menu_file
|
||||||
|
global nullid nullid2 gitdir
|
||||||
|
|
||||||
|
set from_index {}
|
||||||
if {$cmitmode eq "tree"} {
|
if {$cmitmode eq "tree"} {
|
||||||
set id $currentid
|
set id $currentid
|
||||||
set line [expr {$diff_menu_line - $diff_menu_filebase}]
|
set line [expr {$diff_menu_line - $diff_menu_filebase}]
|
||||||
@ -3279,11 +3297,46 @@ proc show_line_source {} {
|
|||||||
mark_ctext_line $diff_menu_line
|
mark_ctext_line $diff_menu_line
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
set id [lindex $parents($curview,$currentid) [expr {$pi - 1}]]
|
incr pi -1
|
||||||
|
if {$currentid eq $nullid} {
|
||||||
|
if {$pi > 0} {
|
||||||
|
# must be a merge in progress...
|
||||||
|
if {[catch {
|
||||||
|
# get the last line from .git/MERGE_HEAD
|
||||||
|
set f [open [file join $gitdir MERGE_HEAD] r]
|
||||||
|
set id [lindex [split [read $f] "\n"] end-1]
|
||||||
|
close $f
|
||||||
|
} err]} {
|
||||||
|
error_popup [mc "Couldn't read merge head: %s" $err]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} elseif {$parents($curview,$currentid) eq $nullid2} {
|
||||||
|
# need to do the blame from the index
|
||||||
|
if {[catch {
|
||||||
|
set from_index [index_sha1 $flist_menu_file]
|
||||||
|
} err]} {
|
||||||
|
error_popup [mc "Error reading index: %s" $err]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
set id [lindex $parents($curview,$currentid) $pi]
|
||||||
|
}
|
||||||
set line [lindex $h 1]
|
set line [lindex $h 1]
|
||||||
}
|
}
|
||||||
|
set blameargs {}
|
||||||
|
if {$from_index ne {}} {
|
||||||
|
lappend blameargs | git cat-file blob $from_index
|
||||||
|
}
|
||||||
|
lappend blameargs | git blame -p -L$line,+1
|
||||||
|
if {$from_index ne {}} {
|
||||||
|
lappend blameargs --contents -
|
||||||
|
} else {
|
||||||
|
lappend blameargs $id
|
||||||
|
}
|
||||||
|
lappend blameargs -- $flist_menu_file
|
||||||
if {[catch {
|
if {[catch {
|
||||||
set f [open [list | git blame -p -L$line,+1 $id -- $flist_menu_file] r]
|
set f [open $blameargs r]
|
||||||
} err]} {
|
} err]} {
|
||||||
error_popup [mc "Couldn't start git blame: %s" $err]
|
error_popup [mc "Couldn't start git blame: %s" $err]
|
||||||
return
|
return
|
||||||
@ -3305,7 +3358,7 @@ proc stopblaming {} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc read_line_source {fd inst} {
|
proc read_line_source {fd inst} {
|
||||||
global blamestuff curview commfd blameinst
|
global blamestuff curview commfd blameinst nullid nullid2
|
||||||
|
|
||||||
while {[gets $fd line] >= 0} {
|
while {[gets $fd line] >= 0} {
|
||||||
lappend blamestuff($inst) $line
|
lappend blamestuff($inst) $line
|
||||||
@ -3337,6 +3390,11 @@ proc read_line_source {fd inst} {
|
|||||||
}
|
}
|
||||||
if {$fname ne {}} {
|
if {$fname ne {}} {
|
||||||
# all looks good, select it
|
# all looks good, select it
|
||||||
|
if {$id eq $nullid} {
|
||||||
|
# blame uses all-zeroes to mean not committed,
|
||||||
|
# which would mean a change in the index
|
||||||
|
set id $nullid2
|
||||||
|
}
|
||||||
if {[commitinview $id $curview]} {
|
if {[commitinview $id $curview]} {
|
||||||
selectline [rowofcommit $id] 1 [list $fname $lnum]
|
selectline [rowofcommit $id] 1 [list $fname $lnum]
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user