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

gitk: Turn short SHA1 names into links too

This changes the link detection logic to accept strings of between 6 and 40 hex characters as a possible SHA1 ID of another commit, rather than insisting on seeing the full 40 hex characters. To make the logic that turns a possible link into an actual link work with abbreviated IDs, this changes the way the commitinterest array is used, and puts the code that deals with it in a pair of new functions. The commitinterest array is now indexed by just the first 4 characters of the interesting SHA1 ID, and each element is a list of id + command pairs. This also pulls out the logic for expanding an abbreviated SHA1 to the list of matching full IDs into its own function (the way it is done is still the same slow way it was done before, which should be improved some day). This also fixes the bug where clicking on a link would take you to the wrong commit if the line number of the target had changed since the link was made. This is based on a patch by Linus Torvalds, but totally rewritten by me. Signed-off-by: Paul Mackerras <paulus@samba.org>

Paul Mackerras committed Oct 21, 2008 at 10:18 UTC d375ef9b1483c3c828d78ce08adae6aae8e19f75
1 file changed +77 -30
gitk
+77 -30
@@ -307,7 +307,7 @@ proc start_rev_list {view} {
307 global startmsecs commitidx viewcomplete curview
308 global tclencoding
309 global viewargs viewargscmd viewfiles vfilelimit
310 - global showlocalchanges commitinterest
310 + global showlocalchanges
311 global viewactive viewinstances vmergeonly
312 global mainheadid
313 global vcanopt vflags vrevs vorigargs
@@ -368,7 +368,7 @@ proc start_rev_list {view} {
368 set i [reg_instance $fd]
369 set viewinstances($view) [list $i]
370 if {$showlocalchanges && $mainheadid ne {}} {
371 - lappend commitinterest($mainheadid) {dodiffindex}
371 + interestedin $mainheadid dodiffindex
372 }
373 fconfigure $fd -blocking 0 -translation lf -eofchar {}
374 if {$tclencoding != {}} {
@@ -1231,7 +1231,7 @@ proc commitonrow {row} {
1231
1232 proc closevarcs {v} {
1233 global varctok varccommits varcid parents children
1234 - global cmitlisted commitidx commitinterest vtokmod
1234 + global cmitlisted commitidx vtokmod
1235
1236 set missing_parents 0
1237 set scripts {}
@@ -1256,12 +1256,7 @@ proc closevarcs {v} {
1256 }
1257 lappend varccommits($v,$b) $p
1258 incr commitidx($v)
1259 - if {[info exists commitinterest($p)]} {
1260 - foreach script $commitinterest($p) {
1261 - lappend scripts [string map [list "%I" $p] $script]
1262 - }
1263 - unset commitinterest($id)
1264 - }
1259 + set scripts [check_interest $p $scripts]
1260 }
1261 }
1262 if {$missing_parents > 0} {
@@ -1297,8 +1292,41 @@ proc rewrite_commit {v id rwid} {
1292 }
1293 }
1294
1295 +# Mechanism for registering a command to be executed when we come
1296 +# across a particular commit. To handle the case when only the
1297 +# prefix of the commit is known, the commitinterest array is now
1298 +# indexed by the first 4 characters of the ID. Each element is a
1299 +# list of id, cmd pairs.
1300 +proc interestedin {id cmd} {
1301 + global commitinterest
1302 +
1303 + lappend commitinterest([string range $id 0 3]) $id $cmd
1304 +}
1305 +
1306 +proc check_interest {id scripts} {
1307 + global commitinterest
1308 +
1309 + set prefix [string range $id 0 3]
1310 + if {[info exists commitinterest($prefix)]} {
1311 + set newlist {}
1312 + foreach {i script} $commitinterest($prefix) {
1313 + if {[string match "$i*" $id]} {
1314 + lappend scripts [string map [list "%I" $id "%P" $i] $script]
1315 + } else {
1316 + lappend newlist $i $script
1317 + }
1318 + }
1319 + if {$newlist ne {}} {
1320 + set commitinterest($prefix) $newlist
1321 + } else {
1322 + unset commitinterest($prefix)
1323 + }
1324 + }
1325 + return $scripts
1326 +}
1327 +
1328 proc getcommitlines {fd inst view updating} {
1301 - global cmitlisted commitinterest leftover
1329 + global cmitlisted leftover
1330 global commitidx commitdata vdatemode
1331 global parents children curview hlview
1332 global idpending ordertok
@@ -1474,12 +1502,7 @@ proc getcommitlines {fd inst view updating} {
1502 incr i
1503 }
1504
1477 - if {[info exists commitinterest($id)]} {
1478 - foreach script $commitinterest($id) {
1479 - lappend scripts [string map [list "%I" $id] $script]
1480 - }
1481 - unset commitinterest($id)
1482 - }
1505 + set scripts [check_interest $id $scripts]
1506 set gotsome 1
1507 }
1508 if {$gotsome} {
@@ -1608,6 +1631,19 @@ proc getcommit {id} {
1631 return 1
1632 }
1633
1634 +# Expand an abbreviated commit ID to a list of full 40-char IDs that match
1635 +# and are present in the current view.
1636 +# This is fairly slow...
1637 +proc longid {prefix} {
1638 + global varcid curview
1639 +
1640 + set ids {}
1641 + foreach match [array names varcid "$curview,$prefix*"] {
1642 + lappend ids [lindex [split $match ","] 1]
1643 + }
1644 + return $ids
1645 +}
1646 +
1647 proc readrefs {} {
1648 global tagids idtags headids idheads tagobjid
1649 global otherrefids idotherrefs mainhead mainheadid
@@ -4119,7 +4155,7 @@ proc visiblerows {} {
4155 proc layoutmore {} {
4156 global commitidx viewcomplete curview
4157 global numcommits pending_select curview
4122 - global lastscrollset lastscrollrows commitinterest
4158 + global lastscrollset lastscrollrows
4159
4160 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
4161 [clock clicks -milliseconds] - $lastscrollset > 500} {
@@ -4140,7 +4176,7 @@ proc doshowlocalchanges {} {
4176 if {[commitinview $mainheadid $curview]} {
4177 dodiffindex
4178 } else {
4143 - lappend commitinterest($mainheadid) {dodiffindex}
4179 + interestedin $mainheadid dodiffindex
4180 }
4181 }
4182
@@ -5795,11 +5831,11 @@ proc commit_descriptor {p} {
5831 # append some text to the ctext widget, and make any SHA1 ID
5832 # that we know about be a clickable link.
5833 proc appendwithlinks {text tags} {
5798 - global ctext linknum curview pendinglinks
5834 + global ctext linknum curview
5835
5836 set start [$ctext index "end - 1c"]
5837 $ctext insert end $text $tags
5802 - set links [regexp -indices -all -inline {[0-9a-f]{40}} $text]
5838 + set links [regexp -indices -all -inline {\m[0-9a-f]{6,40}\M} $text]
5839 foreach l $links {
5840 set s [lindex $l 0]
5841 set e [lindex $l 1]
@@ -5813,16 +5849,27 @@ proc appendwithlinks {text tags} {
5849 }
5850
5851 proc setlink {id lk} {
5816 - global curview ctext pendinglinks commitinterest
5852 + global curview ctext pendinglinks
5853
5818 - if {[commitinview $id $curview]} {
5854 + set known 0
5855 + if {[string length $id] < 40} {
5856 + set matches [longid $id]
5857 + if {[llength $matches] > 0} {
5858 + if {[llength $matches] > 1} return
5859 + set known 1
5860 + set id [lindex $matches 0]
5861 + }
5862 + } else {
5863 + set known [commitinview $id $curview]
5864 + }
5865 + if {$known} {
5866 $ctext tag conf $lk -foreground blue -underline 1
5820 - $ctext tag bind $lk <1> [list selectline [rowofcommit $id] 1]
5867 + $ctext tag bind $lk <1> [list selbyid $id]
5868 $ctext tag bind $lk <Enter> {linkcursor %W 1}
5869 $ctext tag bind $lk <Leave> {linkcursor %W -1}
5870 } else {
5871 lappend pendinglinks($id) $lk
5825 - lappend commitinterest($id) {makelink %I}
5872 + interestedin $id {makelink %P}
5873 }
5874 }
5875
@@ -7138,13 +7185,13 @@ proc gotocommit {} {
7185 } else {
7186 set id [string tolower $sha1string]
7187 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
7141 - set matches [array names varcid "$curview,$id*"]
7188 + set matches [longid $id]
7189 if {$matches ne {}} {
7190 if {[llength $matches] > 1} {
7191 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
7192 return
7193 }
7147 - set id [lindex [split [lindex $matches 0] ","] 1]
7194 + set id [lindex $matches 0]
7195 }
7196 }
7197 }
@@ -7992,7 +8039,7 @@ proc reflistfilter_change {n1 n2 op} {
8039
8040 proc refill_reflist {} {
8041 global reflist reflistfilter showrefstop headids tagids otherrefids
7995 - global curview commitinterest
8042 + global curview
8043
8044 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
8045 set refs {}
@@ -8001,7 +8048,7 @@ proc refill_reflist {} {
8048 if {[commitinview $headids($n) $curview]} {
8049 lappend refs [list $n H]
8050 } else {
8004 - set commitinterest($headids($n)) {run refill_reflist}
8051 + interestedin $headids($n) {run refill_reflist}
8052 }
8053 }
8054 }
@@ -8010,7 +8057,7 @@ proc refill_reflist {} {
8057 if {[commitinview $tagids($n) $curview]} {
8058 lappend refs [list $n T]
8059 } else {
8013 - set commitinterest($tagids($n)) {run refill_reflist}
8060 + interestedin $tagids($n) {run refill_reflist}
8061 }
8062 }
8063 }
@@ -8019,7 +8066,7 @@ proc refill_reflist {} {
8066 if {[commitinview $otherrefids($n) $curview]} {
8067 lappend refs [list $n o]
8068 } else {
8022 - set commitinterest($otherrefids($n)) {run refill_reflist}
8069 + interestedin $otherrefids($n) {run refill_reflist}
8070 }
8071 }
8072 }