Skip to content

Commit d375ef9

Browse files
committed
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 <[email protected]>
1 parent 7905603 commit d375ef9

File tree

1 file changed

+77
-30
lines changed

1 file changed

+77
-30
lines changed

gitk

Lines changed: 77 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ proc start_rev_list {view} {
307307
global startmsecs commitidx viewcomplete curview
308308
global tclencoding
309309
global viewargs viewargscmd viewfiles vfilelimit
310-
global showlocalchanges commitinterest
310+
global showlocalchanges
311311
global viewactive viewinstances vmergeonly
312312
global mainheadid
313313
global vcanopt vflags vrevs vorigargs
@@ -368,7 +368,7 @@ proc start_rev_list {view} {
368368
set i [reg_instance $fd]
369369
set viewinstances($view) [list $i]
370370
if {$showlocalchanges && $mainheadid ne {}} {
371-
lappend commitinterest($mainheadid) {dodiffindex}
371+
interestedin $mainheadid dodiffindex
372372
}
373373
fconfigure $fd -blocking 0 -translation lf -eofchar {}
374374
if {$tclencoding != {}} {
@@ -1231,7 +1231,7 @@ proc commitonrow {row} {
12311231

12321232
proc closevarcs {v} {
12331233
global varctok varccommits varcid parents children
1234-
global cmitlisted commitidx commitinterest vtokmod
1234+
global cmitlisted commitidx vtokmod
12351235

12361236
set missing_parents 0
12371237
set scripts {}
@@ -1256,12 +1256,7 @@ proc closevarcs {v} {
12561256
}
12571257
lappend varccommits($v,$b) $p
12581258
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]
12651260
}
12661261
}
12671262
if {$missing_parents > 0} {
@@ -1297,8 +1292,41 @@ proc rewrite_commit {v id rwid} {
12971292
}
12981293
}
12991294

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+
13001328
proc getcommitlines {fd inst view updating} {
1301-
global cmitlisted commitinterest leftover
1329+
global cmitlisted leftover
13021330
global commitidx commitdata vdatemode
13031331
global parents children curview hlview
13041332
global idpending ordertok
@@ -1474,12 +1502,7 @@ proc getcommitlines {fd inst view updating} {
14741502
incr i
14751503
}
14761504

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]
14831506
set gotsome 1
14841507
}
14851508
if {$gotsome} {
@@ -1608,6 +1631,19 @@ proc getcommit {id} {
16081631
return 1
16091632
}
16101633

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+
16111647
proc readrefs {} {
16121648
global tagids idtags headids idheads tagobjid
16131649
global otherrefids idotherrefs mainhead mainheadid
@@ -4119,7 +4155,7 @@ proc visiblerows {} {
41194155
proc layoutmore {} {
41204156
global commitidx viewcomplete curview
41214157
global numcommits pending_select curview
4122-
global lastscrollset lastscrollrows commitinterest
4158+
global lastscrollset lastscrollrows
41234159

41244160
if {$lastscrollrows < 100 || $viewcomplete($curview) ||
41254161
[clock clicks -milliseconds] - $lastscrollset > 500} {
@@ -4140,7 +4176,7 @@ proc doshowlocalchanges {} {
41404176
if {[commitinview $mainheadid $curview]} {
41414177
dodiffindex
41424178
} else {
4143-
lappend commitinterest($mainheadid) {dodiffindex}
4179+
interestedin $mainheadid dodiffindex
41444180
}
41454181
}
41464182

@@ -5795,11 +5831,11 @@ proc commit_descriptor {p} {
57955831
# append some text to the ctext widget, and make any SHA1 ID
57965832
# that we know about be a clickable link.
57975833
proc appendwithlinks {text tags} {
5798-
global ctext linknum curview pendinglinks
5834+
global ctext linknum curview
57995835

58005836
set start [$ctext index "end - 1c"]
58015837
$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]
58035839
foreach l $links {
58045840
set s [lindex $l 0]
58055841
set e [lindex $l 1]
@@ -5813,16 +5849,27 @@ proc appendwithlinks {text tags} {
58135849
}
58145850

58155851
proc setlink {id lk} {
5816-
global curview ctext pendinglinks commitinterest
5852+
global curview ctext pendinglinks
58175853

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} {
58195866
$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]
58215868
$ctext tag bind $lk <Enter> {linkcursor %W 1}
58225869
$ctext tag bind $lk <Leave> {linkcursor %W -1}
58235870
} else {
58245871
lappend pendinglinks($id) $lk
5825-
lappend commitinterest($id) {makelink %I}
5872+
interestedin $id {makelink %P}
58265873
}
58275874
}
58285875

@@ -7138,13 +7185,13 @@ proc gotocommit {} {
71387185
} else {
71397186
set id [string tolower $sha1string]
71407187
if {[regexp {^[0-9a-f]{4,39}$} $id]} {
7141-
set matches [array names varcid "$curview,$id*"]
7188+
set matches [longid $id]
71427189
if {$matches ne {}} {
71437190
if {[llength $matches] > 1} {
71447191
error_popup [mc "Short SHA1 id %s is ambiguous" $id]
71457192
return
71467193
}
7147-
set id [lindex [split [lindex $matches 0] ","] 1]
7194+
set id [lindex $matches 0]
71487195
}
71497196
}
71507197
}
@@ -7992,7 +8039,7 @@ proc reflistfilter_change {n1 n2 op} {
79928039

79938040
proc refill_reflist {} {
79948041
global reflist reflistfilter showrefstop headids tagids otherrefids
7995-
global curview commitinterest
8042+
global curview
79968043

79978044
if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
79988045
set refs {}
@@ -8001,7 +8048,7 @@ proc refill_reflist {} {
80018048
if {[commitinview $headids($n) $curview]} {
80028049
lappend refs [list $n H]
80038050
} else {
8004-
set commitinterest($headids($n)) {run refill_reflist}
8051+
interestedin $headids($n) {run refill_reflist}
80058052
}
80068053
}
80078054
}
@@ -8010,7 +8057,7 @@ proc refill_reflist {} {
80108057
if {[commitinview $tagids($n) $curview]} {
80118058
lappend refs [list $n T]
80128059
} else {
8013-
set commitinterest($tagids($n)) {run refill_reflist}
8060+
interestedin $tagids($n) {run refill_reflist}
80148061
}
80158062
}
80168063
}
@@ -8019,7 +8066,7 @@ proc refill_reflist {} {
80198066
if {[commitinview $otherrefids($n) $curview]} {
80208067
lappend refs [list $n o]
80218068
} else {
8022-
set commitinterest($otherrefids($n)) {run refill_reflist}
8069+
interestedin $otherrefids($n) {run refill_reflist}
80238070
}
80248071
}
80258072
}

0 commit comments

Comments
 (0)