Merge git://git.kernel.org/pub/scm/gitk/gitk

* git://git.kernel.org/pub/scm/gitk/gitk:
  gitk: Turn short SHA1 names into links too
  gitk: Regenerate .po files
  gitk: New way of constructing menus that allows for Alt+letter accelerators
  gitk: Bind Key-Return to create on new branch dialog
  gitk: Fix binding for <Return> in sha1 entry field
  gitk: Clean up file encoding code and add enable/disable option
  gitk: Implement batch lookup and caching of encoding attrs
  gitk: Enhance file encoding support
  gitk: Add untranslated error messages to translation
  gitk: Fix a bug in collapsing deeply nested trees
  gitk: Use <Button-2> for context menus on OSX
This commit is contained in:
Junio C Hamano
2008-10-20 22:16:09 -07:00
5 changed files with 1340 additions and 1067 deletions

View File

@ -269,7 +269,7 @@ proc parseviewrevs {view revs} {
lappend badrev $line
}
}
error_popup "Error parsing revisions: $err"
error_popup "[mc "Error parsing revisions:"] $err"
return {}
}
set ret {}
@ -307,7 +307,7 @@ proc start_rev_list {view} {
global startmsecs commitidx viewcomplete curview
global tclencoding
global viewargs viewargscmd viewfiles vfilelimit
global showlocalchanges commitinterest
global showlocalchanges
global viewactive viewinstances vmergeonly
global mainheadid
global vcanopt vflags vrevs vorigargs
@ -324,7 +324,7 @@ proc start_rev_list {view} {
if {[catch {
set str [exec sh -c $viewargscmd($view)]
} err]} {
error_popup "Error executing --argscmd command: $err"
error_popup "[mc "Error executing --argscmd command:"] $err"
return 0
}
set args [concat $args [split $str "\n"]]
@ -368,7 +368,7 @@ proc start_rev_list {view} {
set i [reg_instance $fd]
set viewinstances($view) [list $i]
if {$showlocalchanges && $mainheadid ne {}} {
lappend commitinterest($mainheadid) {dodiffindex}
interestedin $mainheadid dodiffindex
}
fconfigure $fd -blocking 0 -translation lf -eofchar {}
if {$tclencoding != {}} {
@ -500,7 +500,7 @@ proc updatecommits {} {
set fd [open [concat | git log --no-color -z --pretty=raw --parents \
--boundary $args "--" $vfilelimit($view)] r]
} err]} {
error_popup "Error executing git log: $err"
error_popup "[mc "Error executing git log:"] $err"
return
}
if {$viewactive($view) == 0} {
@ -1231,7 +1231,7 @@ proc commitonrow {row} {
proc closevarcs {v} {
global varctok varccommits varcid parents children
global cmitlisted commitidx commitinterest vtokmod
global cmitlisted commitidx vtokmod
set missing_parents 0
set scripts {}
@ -1256,12 +1256,7 @@ proc closevarcs {v} {
}
lappend varccommits($v,$b) $p
incr commitidx($v)
if {[info exists commitinterest($p)]} {
foreach script $commitinterest($p) {
lappend scripts [string map [list "%I" $p] $script]
}
unset commitinterest($id)
}
set scripts [check_interest $p $scripts]
}
}
if {$missing_parents > 0} {
@ -1297,8 +1292,41 @@ proc rewrite_commit {v id rwid} {
}
}
# Mechanism for registering a command to be executed when we come
# across a particular commit. To handle the case when only the
# prefix of the commit is known, the commitinterest array is now
# indexed by the first 4 characters of the ID. Each element is a
# list of id, cmd pairs.
proc interestedin {id cmd} {
global commitinterest
lappend commitinterest([string range $id 0 3]) $id $cmd
}
proc check_interest {id scripts} {
global commitinterest
set prefix [string range $id 0 3]
if {[info exists commitinterest($prefix)]} {
set newlist {}
foreach {i script} $commitinterest($prefix) {
if {[string match "$i*" $id]} {
lappend scripts [string map [list "%I" $id "%P" $i] $script]
} else {
lappend newlist $i $script
}
}
if {$newlist ne {}} {
set commitinterest($prefix) $newlist
} else {
unset commitinterest($prefix)
}
}
return $scripts
}
proc getcommitlines {fd inst view updating} {
global cmitlisted commitinterest leftover
global cmitlisted leftover
global commitidx commitdata vdatemode
global parents children curview hlview
global idpending ordertok
@ -1474,12 +1502,7 @@ proc getcommitlines {fd inst view updating} {
incr i
}
if {[info exists commitinterest($id)]} {
foreach script $commitinterest($id) {
lappend scripts [string map [list "%I" $id] $script]
}
unset commitinterest($id)
}
set scripts [check_interest $id $scripts]
set gotsome 1
}
if {$gotsome} {
@ -1608,6 +1631,19 @@ proc getcommit {id} {
return 1
}
# Expand an abbreviated commit ID to a list of full 40-char IDs that match
# and are present in the current view.
# This is fairly slow...
proc longid {prefix} {
global varcid curview
set ids {}
foreach match [array names varcid "$curview,$prefix*"] {
lappend ids [lindex [split $match ","] 1]
}
return $ids
}
proc readrefs {} {
global tagids idtags headids idheads tagobjid
global otherrefids idotherrefs mainhead mainheadid
@ -1750,6 +1786,53 @@ proc setoptions {} {
option add *Entry.font uifont startupFile
}
# Make a menu and submenus.
# m is the window name for the menu, items is the list of menu items to add.
# Each item is a list {mc label type description options...}
# mc is ignored; it's so we can put mc there to alert xgettext
# label is the string that appears in the menu
# type is cascade, command or radiobutton (should add checkbutton)
# description depends on type; it's the sublist for cascade, the
# command to invoke for command, or {variable value} for radiobutton
proc makemenu {m items} {
menu $m
foreach i $items {
set name [mc [lindex $i 1]]
set type [lindex $i 2]
set thing [lindex $i 3]
set params [list $type]
if {$name ne {}} {
set u [string first "&" [string map {&& x} $name]]
lappend params -label [string map {&& & & {}} $name]
if {$u >= 0} {
lappend params -underline $u
}
}
switch -- $type {
"cascade" {
set submenu [string tolower [string map {& ""} [lindex $i 1]]]
lappend params -menu $m.$submenu
}
"command" {
lappend params -command $thing
}
"radiobutton" {
lappend params -variable [lindex $thing 0] \
-value [lindex $thing 1]
}
}
eval $m add $params [lrange $i 4 end]
if {$type eq "cascade"} {
makemenu $m.$submenu $thing
}
}
}
# translate string and remove ampersands
proc mca {str} {
return [string map {&& & & {}} [mc $str]]
}
proc makewindow {} {
global canv canv2 canv3 linespc charspc ctext cflist cscroll
global tabstop
@ -1767,33 +1850,31 @@ proc makewindow {} {
global rprogitem rprogcoord rownumsel numcommits
global have_tk85
menu .bar
.bar add cascade -label [mc "File"] -menu .bar.file
menu .bar.file
.bar.file add command -label [mc "Update"] -command updatecommits
.bar.file add command -label [mc "Reload"] -command reloadcommits
.bar.file add command -label [mc "Reread references"] -command rereadrefs
.bar.file add command -label [mc "List references"] -command showrefs
.bar.file add command -label [mc "Quit"] -command doquit
menu .bar.edit
.bar add cascade -label [mc "Edit"] -menu .bar.edit
.bar.edit add command -label [mc "Preferences"] -command doprefs
menu .bar.view
.bar add cascade -label [mc "View"] -menu .bar.view
.bar.view add command -label [mc "New view..."] -command {newview 0}
.bar.view add command -label [mc "Edit view..."] -command editview \
-state disabled
.bar.view add command -label [mc "Delete view"] -command delview -state disabled
.bar.view add separator
.bar.view add radiobutton -label [mc "All files"] -command {showview 0} \
-variable selectedview -value 0
menu .bar.help
.bar add cascade -label [mc "Help"] -menu .bar.help
.bar.help add command -label [mc "About gitk"] -command about
.bar.help add command -label [mc "Key bindings"] -command keys
.bar.help configure
# The "mc" arguments here are purely so that xgettext
# sees the following string as needing to be translated
makemenu .bar {
{mc "File" cascade {
{mc "Update" command updatecommits -accelerator F5}
{mc "Reload" command reloadcommits}
{mc "Reread references" command rereadrefs}
{mc "List references" command showrefs}
{mc "Quit" command doquit}
}}
{mc "Edit" cascade {
{mc "Preferences" command doprefs}
}}
{mc "View" cascade {
{mc "New view..." command {newview 0}}
{mc "Edit view..." command editview -state disabled}
{mc "Delete view" command delview -state disabled}
{xx "" separator}
{mc "All files" radiobutton {selectedview 0} -command {showview 0}}
}}
{mc "Help" cascade {
{mc "About gitk" command about}
{mc "Key bindings" command keys}
}}
}
. configure -menu .bar
# the gui has upper and lower half, parts of a paned window.
@ -2161,61 +2242,55 @@ proc makewindow {} {
bind . <Destroy> {stop_backends}
bind . <Button-1> "click %W"
bind $fstring <Key-Return> {dofind 1 1}
bind $sha1entry <Key-Return> gotocommit
bind $sha1entry <Key-Return> {gotocommit; break}
bind $sha1entry <<PasteSelection>> clearsha1
bind $cflist <1> {sel_flist %W %x %y; break}
bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
bind $cflist <Button-3> {pop_flist_menu %W %X %Y %x %y}
global ctxbut
bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
set maincursor [. cget -cursor]
set textcursor [$ctext cget -cursor]
set curtextcursor $textcursor
set rowctxmenu .rowctxmenu
menu $rowctxmenu -tearoff 0
$rowctxmenu add command -label [mc "Diff this -> selected"] \
-command {diffvssel 0}
$rowctxmenu add command -label [mc "Diff selected -> this"] \
-command {diffvssel 1}
$rowctxmenu add command -label [mc "Make patch"] -command mkpatch
$rowctxmenu add command -label [mc "Create tag"] -command mktag
$rowctxmenu add command -label [mc "Write commit to file"] -command writecommit
$rowctxmenu add command -label [mc "Create new branch"] -command mkbranch
$rowctxmenu add command -label [mc "Cherry-pick this commit"] \
-command cherrypick
$rowctxmenu add command -label [mc "Reset HEAD branch to here"] \
-command resethead
makemenu $rowctxmenu {
{mc "Diff this -> selected" command {diffvssel 0}}
{mc "Diff selected -> this" command {diffvssel 1}}
{mc "Make patch" command mkpatch}
{mc "Create tag" command mktag}
{mc "Write commit to file" command writecommit}
{mc "Create new branch" command mkbranch}
{mc "Cherry-pick this commit" command cherrypick}
{mc "Reset HEAD branch to here" command resethead}
}
$rowctxmenu configure -tearoff 0
set fakerowmenu .fakerowmenu
menu $fakerowmenu -tearoff 0
$fakerowmenu add command -label [mc "Diff this -> selected"] \
-command {diffvssel 0}
$fakerowmenu add command -label [mc "Diff selected -> this"] \
-command {diffvssel 1}
$fakerowmenu add command -label [mc "Make patch"] -command mkpatch
# $fakerowmenu add command -label [mc "Commit"] -command {mkcommit 0}
# $fakerowmenu add command -label [mc "Commit all"] -command {mkcommit 1}
# $fakerowmenu add command -label [mc "Revert local changes"] -command revertlocal
makemenu $fakerowmenu {
{mc "Diff this -> selected" command {diffvssel 0}}
{mc "Diff selected -> this" command {diffvssel 1}}
{mc "Make patch" command mkpatch}
}
$fakerowmenu configure -tearoff 0
set headctxmenu .headctxmenu
menu $headctxmenu -tearoff 0
$headctxmenu add command -label [mc "Check out this branch"] \
-command cobranch
$headctxmenu add command -label [mc "Remove this branch"] \
-command rmbranch
makemenu $headctxmenu {
{mc "Check out this branch" command cobranch}
{mc "Remove this branch" command rmbranch}
}
$headctxmenu configure -tearoff 0
global flist_menu
set flist_menu .flistctxmenu
menu $flist_menu -tearoff 0
$flist_menu add command -label [mc "Highlight this too"] \
-command {flist_hl 0}
$flist_menu add command -label [mc "Highlight this only"] \
-command {flist_hl 1}
$flist_menu add command -label [mc "External diff"] \
-command {external_diff}
$flist_menu add command -label [mc "Blame parent commit"] \
-command {external_blame 1}
makemenu $flist_menu {
{mc "Highlight this too" command {flist_hl 0}}
{mc "Highlight this only" command {flist_hl 1}}
{mc "External diff" command {external_diff}}
{mc "Blame parent commit" command {external_blame 1}}
}
$flist_menu configure -tearoff 0
}
# Windows sends all mouse wheel events to the current focused window, not
@ -2331,7 +2406,7 @@ proc savestuff {w} {
global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
global cmitmode wrapcomment datetimeformat limitdiffs
global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
global autoselect extdifftool
global autoselect extdifftool perfile_attrs
if {$stuffsaved} return
if {![winfo viewable .]} return
@ -2358,6 +2433,7 @@ proc savestuff {w} {
puts $f [list set diffcontext $diffcontext]
puts $f [list set selectbgcolor $selectbgcolor]
puts $f [list set extdifftool $extdifftool]
puts $f [list set perfile_attrs $perfile_attrs]
puts $f "set geometry(main) [wm geometry .]"
puts $f "set geometry(topwidth) [winfo width .tf]"
@ -2705,7 +2781,7 @@ proc treeopendir {w dir} {
$w insert e:$ix $e [highlight_tag $de]
}
}
$w mark gravity e:$ix left
$w mark gravity e:$ix right
$w conf -state disabled
set treediropen($dir) 1
set top [lindex [split [$w index @0,0] .] 0]
@ -2936,7 +3012,7 @@ proc save_file_from_commit {filename output what} {
if {[string match "fatal: bad revision *" $err]} {
return $nullfile
}
error_popup "Error getting \"$filename\" from $what: $err"
error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
return {}
}
return $output
@ -2993,7 +3069,7 @@ proc external_diff {} {
set gitktmpdir [file join [file dirname $gitdir] \
[format ".gitk-tmp.%s" [pid]]]
if {[catch {file mkdir $gitktmpdir} err]} {
error_popup "Error creating temporary directory $gitktmpdir: $err"
error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
unset gitktmpdir
return
}
@ -3002,7 +3078,7 @@ proc external_diff {} {
incr diffnum
set diffdir [file join $gitktmpdir $diffnum]
if {[catch {file mkdir $diffdir} err]} {
error_popup "Error creating temporary directory $diffdir: $err"
error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
return
}
@ -3015,7 +3091,7 @@ proc external_diff {} {
[list $difffromfile $difftofile]]
if {[catch {set fl [open $cmd r]} err]} {
file delete -force $diffdir
error_popup [mc "$extdifftool: command failed: $err"]
error_popup "$extdifftool: [mc "command failed:"] $err"
} else {
fconfigure $fl -blocking 0
filerun $fl [list delete_at_eof $fl $diffdir]
@ -3040,7 +3116,7 @@ proc external_blame {parent_idx} {
}
if {[catch {exec git gui blame $base_commit $flist_menu_file &} err]} {
error_popup [mc "git gui blame: command failed: $err"]
error_popup "[mc "git gui blame: command failed:"] $err"
}
}
@ -3049,7 +3125,7 @@ proc delete_at_eof {f dir} {
while {[gets $f line] >= 0} {}
if {[eof $f]} {
if {[catch {close $f} err]} {
error_popup "External diff viewer failed: $err"
error_popup "[mc "External diff viewer failed:"] $err"
}
file delete -force $dir
return 0
@ -3374,8 +3450,8 @@ proc showview {n} {
set curview $n
set selectedview $n
.bar.view entryconf [mc "Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
.bar.view entryconf [mc "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
.bar.view entryconf [mca "Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
.bar.view entryconf [mca "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
run refill_reflist
if {![info exists viewcomplete($n)]} {
@ -4079,7 +4155,7 @@ proc visiblerows {} {
proc layoutmore {} {
global commitidx viewcomplete curview
global numcommits pending_select curview
global lastscrollset lastscrollrows commitinterest
global lastscrollset lastscrollrows
if {$lastscrollrows < 100 || $viewcomplete($curview) ||
[clock clicks -milliseconds] - $lastscrollset > 500} {
@ -4100,7 +4176,7 @@ proc doshowlocalchanges {} {
if {[commitinview $mainheadid $curview]} {
dodiffindex
} else {
lappend commitinterest($mainheadid) {dodiffindex}
interestedin $mainheadid dodiffindex
}
}
@ -4919,7 +4995,7 @@ proc drawcmittext {id row col} {
global rowtextx idpos idtags idheads idotherrefs
global linehtag linentag linedtag selectedline
global canvxmax boldrows boldnamerows fgcolor
global mainheadid nullid nullid2 circleitem circlecolors
global mainheadid nullid nullid2 circleitem circlecolors ctxbut
# listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
set listed $cmitlisted($curview,$id)
@ -4992,7 +5068,7 @@ proc drawcmittext {id row col} {
}
set linehtag($row) [$canv create text $xt $y -anchor w -fill $fgcolor \
-text $headline -font $font -tags text]
$canv bind $linehtag($row) <Button-3> "rowmenu %X %Y $id"
$canv bind $linehtag($row) $ctxbut "rowmenu %X %Y $id"
set linentag($row) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
-text $name -font $nfont -tags text]
set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
@ -5334,7 +5410,7 @@ proc bindline {t id} {
proc drawtags {id x xt y1} {
global idtags idheads idotherrefs mainhead
global linespc lthickness
global canv rowtextx curview fgcolor bgcolor
global canv rowtextx curview fgcolor bgcolor ctxbut
set marks {}
set ntags 0
@ -5412,7 +5488,7 @@ proc drawtags {id x xt y1} {
if {$ntags >= 0} {
$canv bind $t <1> [list showtag $tag 1]
} elseif {$nheads >= 0} {
$canv bind $t <Button-3> [list headmenu %X %Y $id $tag]
$canv bind $t $ctxbut [list headmenu %X %Y $id $tag]
}
}
return $xt
@ -5755,11 +5831,11 @@ proc commit_descriptor {p} {
# append some text to the ctext widget, and make any SHA1 ID
# that we know about be a clickable link.
proc appendwithlinks {text tags} {
global ctext linknum curview pendinglinks
global ctext linknum curview
set start [$ctext index "end - 1c"]
$ctext insert end $text $tags
set links [regexp -indices -all -inline {[0-9a-f]{40}} $text]
set links [regexp -indices -all -inline {\m[0-9a-f]{6,40}\M} $text]
foreach l $links {
set s [lindex $l 0]
set e [lindex $l 1]
@ -5773,16 +5849,27 @@ proc appendwithlinks {text tags} {
}
proc setlink {id lk} {
global curview ctext pendinglinks commitinterest
global curview ctext pendinglinks
if {[commitinview $id $curview]} {
set known 0
if {[string length $id] < 40} {
set matches [longid $id]
if {[llength $matches] > 0} {
if {[llength $matches] > 1} return
set known 1
set id [lindex $matches 0]
}
} else {
set known [commitinview $id $curview]
}
if {$known} {
$ctext tag conf $lk -foreground blue -underline 1
$ctext tag bind $lk <1> [list selectline [rowofcommit $id] 1]
$ctext tag bind $lk <1> [list selbyid $id]
$ctext tag bind $lk <Enter> {linkcursor %W 1}
$ctext tag bind $lk <Leave> {linkcursor %W -1}
} else {
lappend pendinglinks($id) $lk
lappend commitinterest($id) {makelink %I}
interestedin $id {makelink %P}
}
}
@ -6228,7 +6315,7 @@ proc gettree {id} {
set treepending $id
set treefilelist($id) {}
set treeidlist($id) {}
fconfigure $gtf -blocking 0
fconfigure $gtf -blocking 0 -encoding binary
filerun $gtf [list gettreeline $gtf $id]
}
} else {
@ -6250,11 +6337,12 @@ proc gettreeline {gtf id} {
set line [string range $line 0 [expr {$i-1}]]
if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
set sha1 [lindex $line 2]
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
lappend treeidlist($id) $sha1
}
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
set fname [encoding convertfrom $fname]
lappend treefilelist($id) $fname
}
if {![eof $gtf]} {
@ -6295,7 +6383,7 @@ proc showfile {f} {
return
}
}
fconfigure $bf -blocking 0
fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
filerun $bf [list getblobline $bf $diffids]
$ctext config -state normal
clear_ctext $commentend
@ -6333,6 +6421,7 @@ proc mergediff {id} {
global diffids
global parents
global diffcontext
global diffencoding
global limitdiffs vfilelimit curview
set diffmergeid $id
@ -6346,9 +6435,10 @@ proc mergediff {id} {
error_popup "[mc "Error getting merge diffs:"] $err"
return
}
fconfigure $mdf -blocking 0
fconfigure $mdf -blocking 0 -encoding binary
set mdifffd($id) $mdf
set np [llength $parents($curview,$id)]
set diffencoding [get_path_encoding {}]
settabs $np
filerun $mdf [list getmergediffline $mdf $id $np]
}
@ -6356,6 +6446,7 @@ proc mergediff {id} {
proc getmergediffline {mdf id np} {
global diffmergeid ctext cflist mergemax
global difffilestart mdifffd
global diffencoding
$ctext conf -state normal
set nr 0
@ -6367,18 +6458,22 @@ proc getmergediffline {mdf id np} {
}
if {[regexp {^diff --cc (.*)} $line match fname]} {
# start of a new file
set fname [encoding convertfrom $fname]
$ctext insert end "\n"
set here [$ctext index "end - 1c"]
lappend difffilestart $here
add_flist [list $fname]
set diffencoding [get_path_encoding $fname]
set l [expr {(78 - [string length $fname]) / 2}]
set pad [string range "----------------------------------------" 1 $l]
$ctext insert end "$pad $fname $pad\n" filesep
} elseif {[regexp {^@@} $line]} {
set line [encoding convertfrom $diffencoding $line]
$ctext insert end "$line\n" hunksep
} elseif {[regexp {^[0-9a-f]{40}$} $line] || [regexp {^index} $line]} {
# do nothing
} else {
set line [encoding convertfrom $diffencoding $line]
# parse the prefix - one ' ', '-' or '+' for each parent
set spaces {}
set minuses {}
@ -6513,27 +6608,42 @@ proc gettreediffs {ids} {
set treepending $ids
set treediff {}
fconfigure $gdtf -blocking 0
fconfigure $gdtf -blocking 0 -encoding binary
filerun $gdtf [list gettreediffline $gdtf $ids]
}
proc gettreediffline {gdtf ids} {
global treediff treediffs treepending diffids diffmergeid
global cmitmode vfilelimit curview limitdiffs
global cmitmode vfilelimit curview limitdiffs perfile_attrs
set nr 0
while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
set sublist {}
set max 1000
if {$perfile_attrs} {
# cache_gitattr is slow, and even slower on win32 where we
# have to invoke it for only about 30 paths at a time
set max 500
if {[tk windowingsystem] == "win32"} {
set max 120
}
}
while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
set i [string first "\t" $line]
if {$i >= 0} {
set file [string range $line [expr {$i+1}] end]
if {[string index $file 0] eq "\""} {
set file [lindex $file 0]
}
set file [encoding convertfrom $file]
lappend treediff $file
lappend sublist $file
}
}
if {$perfile_attrs} {
cache_gitattr encoding $sublist
}
if {![eof $gdtf]} {
return [expr {$nr >= 1000? 2: 1}]
return [expr {$nr >= $max? 2: 1}]
}
close $gdtf
if {$limitdiffs && $vfilelimit($curview) ne {}} {
@ -6586,6 +6696,7 @@ proc getblobdiffs {ids} {
global diffcontext
global ignorespace
global limitdiffs vfilelimit curview
global diffencoding
set cmd [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"]
if {$ignorespace} {
@ -6599,7 +6710,8 @@ proc getblobdiffs {ids} {
return
}
set diffinhdr 0
fconfigure $bdf -blocking 0
set diffencoding [get_path_encoding {}]
fconfigure $bdf -blocking 0 -encoding binary
set blobdifffd($ids) $bdf
filerun $bdf [list getblobdiffline $bdf $diffids]
}
@ -6633,6 +6745,7 @@ proc getblobdiffline {bdf ids} {
global diffids blobdifffd ctext curdiffstart
global diffnexthead diffnextnote difffilestart
global diffinhdr treediffs
global diffencoding
set nr 0
$ctext conf -state normal
@ -6670,10 +6783,13 @@ proc getblobdiffline {bdf ids} {
} else {
set fname [string range $line 2 [expr {$i - 1}]]
}
set fname [encoding convertfrom $fname]
set diffencoding [get_path_encoding $fname]
makediffhdr $fname $ids
} elseif {[regexp {^@@ -([0-9]+)(,[0-9]+)? \+([0-9]+)(,[0-9]+)? @@(.*)} \
$line match f1l f1c f2l f2c rest]} {
set line [encoding convertfrom $diffencoding $line]
$ctext insert end "$line\n" hunksep
set diffinhdr 0
@ -6683,6 +6799,7 @@ proc getblobdiffline {bdf ids} {
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
set fname [encoding convertfrom $fname]
set i [lsearch -exact $treediffs($ids) $fname]
if {$i >= 0} {
setinlist difffilestart $i $curdiffstart
@ -6693,6 +6810,8 @@ proc getblobdiffline {bdf ids} {
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
set fname [encoding convertfrom $fname]
set diffencoding [get_path_encoding $fname]
makediffhdr $fname $ids
} elseif {[string compare -length 3 $line "---"] == 0} {
# do nothing
@ -6704,6 +6823,7 @@ proc getblobdiffline {bdf ids} {
$ctext insert end "$line\n" filesep
} else {
set line [encoding convertfrom $diffencoding $line]
set x [string range $line 0 0]
if {$x == "-" || $x == "+"} {
set tag [expr {$x == "+"}]
@ -7065,13 +7185,13 @@ proc gotocommit {} {
} else {
set id [string tolower $sha1string]
if {[regexp {^[0-9a-f]{4,39}$} $id]} {
set matches [array names varcid "$curview,$id*"]
set matches [longid $id]
if {$matches ne {}} {
if {[llength $matches] > 1} {
error_popup [mc "Short SHA1 id %s is ambiguous" $id]
return
}
set id [lindex [split [lindex $matches 0] ","] 1]
set id [lindex $matches 0]
}
}
}
@ -7288,9 +7408,9 @@ proc rowmenu {x y id} {
} else {
set menu $fakerowmenu
}
$menu entryconfigure [mc "Diff this -> selected"] -state $state
$menu entryconfigure [mc "Diff selected -> this"] -state $state
$menu entryconfigure [mc "Make patch"] -state $state
$menu entryconfigure [mca "Diff this -> selected"] -state $state
$menu entryconfigure [mca "Diff selected -> this"] -state $state
$menu entryconfigure [mca "Make patch"] -state $state
tk_popup $menu $x $y
}
@ -7590,6 +7710,7 @@ proc mkbranch {} {
grid $top.id $top.sha1 -sticky w
label $top.nlab -text [mc "Name:"]
entry $top.name -width 40
bind $top.name <Key-Return> "[list mkbrgo $top]"
grid $top.nlab $top.name -sticky w
frame $top.buts
button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
@ -7918,7 +8039,7 @@ proc reflistfilter_change {n1 n2 op} {
proc refill_reflist {} {
global reflist reflistfilter showrefstop headids tagids otherrefids
global curview commitinterest
global curview
if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
set refs {}
@ -7927,7 +8048,7 @@ proc refill_reflist {} {
if {[commitinview $headids($n) $curview]} {
lappend refs [list $n H]
} else {
set commitinterest($headids($n)) {run refill_reflist}
interestedin $headids($n) {run refill_reflist}
}
}
}
@ -7936,7 +8057,7 @@ proc refill_reflist {} {
if {[commitinview $tagids($n) $curview]} {
lappend refs [list $n T]
} else {
set commitinterest($tagids($n)) {run refill_reflist}
interestedin $tagids($n) {run refill_reflist}
}
}
}
@ -7945,7 +8066,7 @@ proc refill_reflist {} {
if {[commitinview $otherrefids($n) $curview]} {
lappend refs [list $n o]
} else {
set commitinterest($otherrefids($n)) {run refill_reflist}
interestedin $otherrefids($n) {run refill_reflist}
}
}
}
@ -9295,7 +9416,7 @@ proc doprefs {} {
global maxwidth maxgraphpct
global oldprefs prefstop showneartags showlocalchanges
global bgcolor fgcolor ctext diffcolors selectbgcolor
global tabstop limitdiffs autoselect extdifftool
global tabstop limitdiffs autoselect extdifftool perfile_attrs
set top .gitkprefs
set prefstop $top
@ -9304,7 +9425,7 @@ proc doprefs {} {
return
}
foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
limitdiffs tabstop} {
limitdiffs tabstop perfile_attrs} {
set oldprefs($v) [set $v]
}
toplevel $top
@ -9346,6 +9467,11 @@ proc doprefs {} {
checkbutton $top.ldiff.b -variable limitdiffs
pack $top.ldiff.b $top.ldiff.l -side left
grid x $top.ldiff -sticky w
frame $top.lattr
label $top.lattr.l -text [mc "Support per-file encodings"] -font optionfont
checkbutton $top.lattr.b -variable perfile_attrs
pack $top.lattr.b $top.lattr.l -side left
grid x $top.lattr -sticky w
entry $top.extdifft -textvariable extdifftool
frame $top.extdifff
@ -9455,7 +9581,7 @@ proc prefscan {} {
global oldprefs prefstop
foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
limitdiffs tabstop} {
limitdiffs tabstop perfile_attrs} {
global $v
set $v $oldprefs($v)
}
@ -9468,7 +9594,7 @@ proc prefsok {} {
global maxwidth maxgraphpct
global oldprefs prefstop showneartags showlocalchanges
global fontpref mainfont textfont uifont
global limitdiffs treediffs
global limitdiffs treediffs perfile_attrs
catch {destroy $prefstop}
unset prefstop
@ -9501,8 +9627,10 @@ proc prefsok {} {
dohidelocalchanges
}
}
if {$limitdiffs != $oldprefs(limitdiffs)} {
# treediffs elements are limited by path
if {$limitdiffs != $oldprefs(limitdiffs) ||
($perfile_attrs && !$oldprefs(perfile_attrs))} {
# treediffs elements are limited by path;
# won't have encodings cached if perfile_attrs was just turned on
catch {unset treediffs}
}
if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
@ -9726,7 +9854,7 @@ set encoding_aliases {
{ ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
{ GBK CP936 MS936 windows-936 }
{ JIS_Encoding csJISEncoding }
{ Shift_JIS MS_Kanji csShiftJIS }
{ Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
{ Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
EUC-JP }
{ Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
@ -9761,14 +9889,17 @@ set encoding_aliases {
}
proc tcl_encoding {enc} {
global encoding_aliases
global encoding_aliases tcl_encoding_cache
if {[info exists tcl_encoding_cache($enc)]} {
return $tcl_encoding_cache($enc)
}
set names [encoding names]
set lcnames [string tolower $names]
set enc [string tolower $enc]
set i [lsearch -exact $lcnames $enc]
if {$i < 0} {
# look for "isonnn" instead of "iso-nnn" or "iso_nnn"
if {[regsub {^iso[-_]} $enc iso encx]} {
if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
set i [lsearch -exact $lcnames $encx]
}
}
@ -9780,7 +9911,7 @@ proc tcl_encoding {enc} {
foreach e $ll {
set i [lsearch -exact $lcnames $e]
if {$i < 0} {
if {[regsub {^iso[-_]} $e iso ex]} {
if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
set i [lsearch -exact $lcnames $ex]
}
}
@ -9789,10 +9920,70 @@ proc tcl_encoding {enc} {
break
}
}
set tclenc {}
if {$i >= 0} {
return [lindex $names $i]
set tclenc [lindex $names $i]
}
return {}
set tcl_encoding_cache($enc) $tclenc
return $tclenc
}
proc gitattr {path attr default} {
global path_attr_cache
if {[info exists path_attr_cache($attr,$path)]} {
set r $path_attr_cache($attr,$path)
} else {
set r "unspecified"
if {![catch {set line [exec git check-attr $attr -- $path]}]} {
regexp "(.*): encoding: (.*)" $line m f r
}
set path_attr_cache($attr,$path) $r
}
if {$r eq "unspecified"} {
return $default
}
return $r
}
proc cache_gitattr {attr pathlist} {
global path_attr_cache
set newlist {}
foreach path $pathlist {
if {![info exists path_attr_cache($attr,$path)]} {
lappend newlist $path
}
}
set lim 1000
if {[tk windowingsystem] == "win32"} {
# windows has a 32k limit on the arguments to a command...
set lim 30
}
while {$newlist ne {}} {
set head [lrange $newlist 0 [expr {$lim - 1}]]
set newlist [lrange $newlist $lim end]
if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
foreach row [split $rlist "\n"] {
if {[regexp "(.*): encoding: (.*)" $row m path value]} {
if {[string index $path 0] eq "\""} {
set path [encoding convertfrom [lindex $path 0]]
}
set path_attr_cache($attr,$path) $value
}
}
}
}
}
proc get_path_encoding {path} {
global gui_encoding perfile_attrs
set tcl_enc $gui_encoding
if {$path ne {} && $perfile_attrs} {
set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
if {$enc2 ne {}} {
set tcl_enc $enc2
}
}
return $tcl_enc
}
# First check that Tcl/Tk is recent enough
@ -9817,6 +10008,19 @@ if {$tclencoding == {}} {
puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
}
set gui_encoding [encoding system]
catch {
set enc [exec git config --get gui.encoding]
if {$enc ne {}} {
set tclenc [tcl_encoding $enc]
if {$tclenc ne {}} {
set gui_encoding $tclenc
} else {
puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
}
}
}
set mainfont {Helvetica 9}
set textfont {Courier 9}
set uifont {Helvetica 9 bold}
@ -9838,6 +10042,7 @@ set showlocalchanges 1
set limitdiffs 1
set datetimeformat "%Y-%m-%d %H:%M:%S"
set autoselect 1
set perfile_attrs 0
set extdifftool "meld"
@ -9851,6 +10056,13 @@ set selectbgcolor gray85
set circlecolors {white blue gray blue blue}
# button for popping up context menus
if {[tk windowingsystem] eq "aqua"} {
set ctxbut <Button-2>
} else {
set ctxbut <Button-3>
}
## For msgcat loading, first locate the installation location.
if { [info exists ::env(GITK_MSGSDIR)] } {
## Msgsdir was manually set in the environment.
@ -10019,8 +10231,8 @@ if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
set viewperm(1) 0
set vdatemode(1) 0
addviewmenu 1
.bar.view entryconf [mc "Edit view..."] -state normal
.bar.view entryconf [mc "Delete view"] -state normal
.bar.view entryconf [mca "Edit view..."] -state normal
.bar.view entryconf [mca "Delete view"] -state normal
}
if {[info exists permviews]} {