set origargs [lreplace $origargs $i $i]
incr i -1
}
- # These request or affect diff output, which we don't want.
- # Some could be used to set our defaults for diff display.
"-[puabwcrRBMC]" -
"--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
"--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
"--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
"-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
"--ignore-space-change" - "-U*" - "--unified=*" {
+ # These request or affect diff output, which we don't want.
+ # Some could be used to set our defaults for diff display.
lappend diffargs $arg
}
- # These cause our parsing of git log's output to fail, or else
- # they're options we want to set ourselves, so ignore them.
"--raw" - "--patch-with-raw" - "--patch-with-stat" -
"--name-only" - "--name-status" - "--color" - "--color-words" -
"--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
"--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
"--timestamp" - "relative-date" - "--date=*" - "--stdin" -
"--objects" - "--objects-edge" - "--reverse" {
+ # These cause our parsing of git log's output to fail, or else
+ # they're options we want to set ourselves, so ignore them.
}
- # These are harmless, and some are even useful
"--stat=*" - "--numstat" - "--shortstat" - "--summary" -
"--check" - "--exit-code" - "--quiet" - "--topo-order" -
"--full-history" - "--dense" - "--sparse" -
"--follow" - "--left-right" - "--encoding=*" {
+ # These are harmless, and some are even useful
lappend glflags $arg
}
- # These mean that we get a subset of the commits
"--diff-filter=*" - "--no-merges" - "--unpacked" -
"--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
"--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
"--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
"--remove-empty" - "--first-parent" - "--cherry-pick" -
- "-S*" - "--pickaxe-all" - "--pickaxe-regex" - {
+ "-S*" - "--pickaxe-all" - "--pickaxe-regex" -
+ "--simplify-by-decoration" {
+ # These mean that we get a subset of the commits
set filtered 1
lappend glflags $arg
}
- # This appears to be the only one that has a value as a
- # separate word following it
"-n" {
+ # This appears to be the only one that has a value as a
+ # separate word following it
set filtered 1
set nextisval 1
lappend glflags $arg
}
- "--not" {
- set notflag [expr {!$notflag}]
- lappend revargs $arg
- }
- "--all" {
+ "--not" - "--all" {
lappend revargs $arg
}
"--merge" {
# git rev-parse doesn't understand --merge
lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
}
- # Other flag arguments including -<n>
"-*" {
+ # Other flag arguments including -<n>
if {[string is digit -strict [string range $arg 1 end]]} {
set filtered 1
} else {
}
lappend glflags $arg
}
- # Non-flag arguments specify commits or ranges of commits
default {
+ # Non-flag arguments specify commits or ranges of commits
if {[string match "*...*" $arg]} {
lappend revargs --gitk-symmetric-diff-marker
}
if {$sdm != 2} {
lappend ret $id
} else {
- lset ret end [lindex $ret end]...$id
+ lset ret end $id...[lindex $ret end]
}
lappend pos $id
}
global viewargs viewargscmd viewfiles vfilelimit
global showlocalchanges
global viewactive viewinstances vmergeonly
- global mainheadid
+ global mainheadid viewmainheadid viewmainheadid_orig
global vcanopt vflags vrevs vorigargs
set startmsecs [clock clicks -milliseconds]
}
set i [reg_instance $fd]
set viewinstances($view) [list $i]
- if {$showlocalchanges && $mainheadid ne {}} {
- interestedin $mainheadid dodiffindex
+ set viewmainheadid($view) $mainheadid
+ set viewmainheadid_orig($view) $mainheadid
+ if {$files ne {} && $mainheadid ne {}} {
+ get_viewmainhead $view
+ }
+ if {$showlocalchanges && $viewmainheadid($view) ne {}} {
+ interestedin $viewmainheadid($view) dodiffindex
}
fconfigure $fd -blocking 0 -translation lf -eofchar {}
if {$tclencoding != {}} {
global curview vcanopt vorigargs vfilelimit viewinstances
global viewactive viewcomplete tclencoding
global startmsecs showneartags showlocalchanges
- global mainheadid pending_select
+ global mainheadid viewmainheadid viewmainheadid_orig pending_select
global isworktree
global varcid vposids vnegids vflags vrevs
set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
- set oldmainid $mainheadid
rereadrefs
- if {$showlocalchanges} {
- if {$mainheadid ne $oldmainid} {
+ set view $curview
+ if {$mainheadid ne $viewmainheadid_orig($view)} {
+ if {$showlocalchanges} {
dohidelocalchanges
}
- if {[commitinview $mainheadid $curview]} {
- dodiffindex
+ set viewmainheadid($view) $mainheadid
+ set viewmainheadid_orig($view) $mainheadid
+ if {$vfilelimit($view) ne {}} {
+ get_viewmainhead $view
}
}
- set view $curview
+ if {$showlocalchanges} {
+ doshowlocalchanges
+ }
if {$vcanopt($view)} {
set oldpos $vposids($view)
set oldneg $vnegids($view)
incr viewactive($view)
set viewcomplete($view) 0
reset_pending_select {}
- nowbusy $view "Reading"
+ nowbusy $view [mc "Reading"]
if {$showneartags} {
getallcommits
}
}
proc splitvarc {p v} {
- global varcid varcstart varccommits varctok
+ global varcid varcstart varccommits varctok vtokmod
global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
set oa $varcid($v,$p)
+ set otok [lindex $varctok($v) $oa]
set ac $varccommits($v,$oa)
set i [lsearch -exact $varccommits($v,$oa) $p]
if {$i <= 0} return
set na [llength $varctok($v)]
# "%" sorts before "0"...
- set tok "[lindex $varctok($v) $oa]%[strrep $i]"
+ set tok "$otok%[strrep $i]"
lappend varctok($v) $tok
lappend varcrow($v) {}
lappend varcix($v) {}
for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
lset vupptr($v) $b $na
}
+ if {[string compare $otok $vtokmod($v)] <= 0} {
+ modify_arc $v $oa
+ }
}
proc renumbervarc {a v} {
return 0
}
+proc do_readcommit {id} {
+ global tclencoding
+
+ # Invoke git-log to handle automatic encoding conversion
+ set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
+ # Read the results using i18n.logoutputencoding
+ fconfigure $fd -translation lf -eofchar {}
+ if {$tclencoding != {}} {
+ fconfigure $fd -encoding $tclencoding
+ }
+ set contents [read $fd]
+ close $fd
+ # Remove the heading line
+ regsub {^commit [0-9a-f]+\n} $contents {} contents
+
+ return $contents
+}
+
proc readcommit {id} {
- if {[catch {set contents [exec git cat-file commit $id]}]} return
- parsecommit $id $contents 0
+ if {[catch {set contents [do_readcommit $id]}]} return
+ parsecommit $id $contents 1
}
proc parsecommit {id contents listed} {
set header [string range $contents 0 [expr {$hdrend - 1}]]
set comment [string range $contents [expr {$hdrend + 2}] end]
foreach line [split $header "\n"] {
+ set line [split $line " "]
set tag [lindex $line 0]
if {$tag == "author"} {
set audate [lindex $line end-1]
- set auname [lrange $line 1 end-2]
+ set auname [join [lrange $line 1 end-2] " "]
} elseif {$tag == "committer"} {
set comdate [lindex $line end-1]
- set comname [lrange $line 1 end-2]
+ set comname [join [lrange $line 1 end-2] " "]
}
}
set headline {}
global tagids idtags headids idheads tagobjid
global otherrefids idotherrefs mainhead mainheadid
global selecthead selectheadid
+ global hideremotes
foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
catch {unset $v}
if {![string match "refs/*" $ref]} continue
set name [string range $ref 5 end]
if {[string match "remotes/*" $name]} {
- if {![string match "*/HEAD" $name]} {
+ if {![string match "*/HEAD" $name] && !$hideremotes} {
set headids($name) $id
lappend idheads($id) $name
}
unset headids($name)
}
-proc show_error {w top msg} {
+proc make_transient {window origin} {
+ global have_tk85
+
+ # In MacOS Tk 8.4 transient appears to work by setting
+ # overrideredirect, which is utterly useless, since the
+ # windows get no border, and are not even kept above
+ # the parent.
+ if {!$have_tk85 && [tk windowingsystem] eq {aqua}} return
+
+ wm transient $window $origin
+
+ # Windows fails to place transient windows normally, so
+ # schedule a callback to center them on the parent.
+ if {[tk windowingsystem] eq {win32}} {
+ after idle [list tk::PlaceWindow $window widget $origin]
+ }
+}
+
+proc show_error {w top msg {mc mc}} {
message $w.m -text $msg -justify center -aspect 400
pack $w.m -side top -fill x -padx 20 -pady 20
- button $w.ok -text [mc OK] -command "destroy $top"
+ button $w.ok -text [$mc OK] -command "destroy $top"
pack $w.ok -side bottom -fill x
bind $top <Visibility> "grab $top; focus $top"
bind $top <Key-Return> "destroy $top"
+ bind $top <Key-space> "destroy $top"
+ bind $top <Key-Escape> "destroy $top"
tkwait window $top
}
-proc error_popup msg {
+proc error_popup {msg {owner .}} {
set w .error
toplevel $w
- wm transient $w .
+ make_transient $w $owner
show_error $w $w $msg
}
-proc confirm_popup msg {
+proc confirm_popup {msg {owner .}} {
global confirm_ok
set confirm_ok 0
set w .confirm
toplevel $w
- wm transient $w .
+ make_transient $w $owner
message $w.m -text $msg -justify center -aspect 400
pack $w.m -side top -fill x -padx 20 -pady 20
button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
button $w.cancel -text [mc Cancel] -command "destroy $w"
pack $w.cancel -side right -fill x
bind $w <Visibility> "grab $w; focus $w"
+ bind $w <Key-Return> "set confirm_ok 1; destroy $w"
+ bind $w <Key-space> "set confirm_ok 1; destroy $w"
+ bind $w <Key-Escape> "destroy $w"
tkwait window $w
return $confirm_ok
}
option add *Button.font uifont startupFile
option add *Checkbutton.font uifont startupFile
option add *Radiobutton.font uifont startupFile
- option add *Menu.font uifont startupFile
+ if {[tk windowingsystem] ne "aqua"} {
+ option add *Menu.font uifont startupFile
+ }
option add *Menubutton.font uifont startupFile
option add *Label.font uifont startupFile
option add *Message.font uifont startupFile
# command to invoke for command, or {variable value} for radiobutton
proc makemenu {m items} {
menu $m
+ if {[tk windowingsystem] eq {aqua}} {
+ set Meta1 Cmd
+ } else {
+ set Meta1 Ctrl
+ }
foreach i $items {
set name [mc [lindex $i 1]]
set type [lindex $i 2]
-value [lindex $thing 1]
}
}
- eval $m add $params [lrange $i 4 end]
+ set tail [lrange $i 4 end]
+ regsub -all {\yMeta1\y} $tail $Meta1 tail
+ eval $m add $params $tail
if {$type eq "cascade"} {
makemenu $m.$submenu $thing
}
# The "mc" arguments here are purely so that xgettext
# sees the following string as needing to be translated
- makemenu .bar {
- {mc "File" cascade {
+ set file {
+ mc "File" cascade {
{mc "Update" command updatecommits -accelerator F5}
- {mc "Reload" command reloadcommits}
+ {mc "Reload" command reloadcommits -accelerator Meta1-F5}
{mc "Reread references" command rereadrefs}
- {mc "List references" command showrefs}
- {mc "Quit" command doquit}
+ {mc "List references" command showrefs -accelerator F2}
+ {xx "" separator}
+ {mc "Start git gui" command {exec git gui &}}
+ {xx "" separator}
+ {mc "Quit" command doquit -accelerator Meta1-Q}
}}
- {mc "Edit" cascade {
+ set edit {
+ mc "Edit" cascade {
{mc "Preferences" command doprefs}
}}
- {mc "View" cascade {
- {mc "New view..." command {newview 0}}
- {mc "Edit view..." command editview -state disabled}
+ set view {
+ mc "View" cascade {
+ {mc "New view..." command {newview 0} -accelerator Shift-F4}
+ {mc "Edit view..." command editview -state disabled -accelerator F4}
{mc "Delete view" command delview -state disabled}
{xx "" separator}
{mc "All files" radiobutton {selectedview 0} -command {showview 0}}
}}
- {mc "Help" cascade {
+ if {[tk windowingsystem] ne "aqua"} {
+ set help {
+ mc "Help" cascade {
+ {mc "About gitk" command about}
+ {mc "Key bindings" command keys}
+ }}
+ set bar [list $file $edit $view $help]
+ } else {
+ proc ::tk::mac::ShowPreferences {} {doprefs}
+ proc ::tk::mac::Quit {} {doquit}
+ lset file end [lreplace [lindex $file end] end-1 end]
+ set apple {
+ xx "Apple" cascade {
{mc "About gitk" command about}
+ {xx "" separator}
+ }}
+ set help {
+ mc "Help" cascade {
{mc "Key bindings" command keys}
}}
+ set bar [list $apple $file $view $help]
}
+ makemenu .bar $bar
. configure -menu .bar
# the gui has upper and lower half, parts of a paned window.
label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: "
pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left
spinbox .bleft.mid.diffcontext -width 5 -font textfont \
- -from 1 -increment 1 -to 10000000 \
+ -from 0 -increment 1 -to 10000000 \
-validate all -validatecommand "diffcontextvalidate %P" \
-textvariable diffcontextstring
.bleft.mid.diffcontext set $diffcontext
}
}
+ if {[info exists geometry(state)] && $geometry(state) eq "zoomed"} {
+ wm state . $geometry(state)
+ }
+
if {[tk windowingsystem] eq {aqua}} {
set M1B M1
+ set ::BM "3"
} else {
set M1B Control
+ set ::BM "2"
}
bind .pwbottom <Configure> {resizecdetpanes %W %w}
set delta [expr {- (%D)}]
allcanvs yview scroll $delta units
}
+ bindall <Shift-MouseWheel> {
+ set delta [expr {- (%D)}]
+ $canv xview scroll $delta units
+ }
}
}
- bindall <2> "canvscan mark %W %x %y"
- bindall <B2-Motion> "canvscan dragto %W %x %y"
+ bindall <$::BM> "canvscan mark %W %x %y"
+ bindall <B$::BM-Motion> "canvscan dragto %W %x %y"
bindkey <Home> selfirstline
bindkey <End> sellastline
bind . <Key-Up> "selnextline -1"
bindkey b prevfile
bindkey d "$ctext yview scroll 18 units"
bindkey u "$ctext yview scroll -18 units"
- bindkey / {dofind 1 1}
+ bindkey / {focus $fstring}
+ bindkey <Key-KP_Divide> {focus $fstring}
bindkey <Key-Return> {dofind 1 1}
bindkey ? {dofind -1 1}
bindkey f nextfile
- bindkey <F5> updatecommits
+ bind . <F5> updatecommits
+ bind . <$M1B-F5> reloadcommits
+ bind . <F2> showrefs
+ bind . <Shift-F4> {newview 0}
+ catch { bind . <Shift-Key-XF86_Switch_VT_4> {newview 0} }
+ bind . <F4> edit_or_newview
bind . <$M1B-q> doquit
bind . <$M1B-f> {dofind 1 1}
bind . <$M1B-g> {dofind 1 0}
{mc "Create new branch" command mkbranch}
{mc "Cherry-pick this commit" command cherrypick}
{mc "Reset HEAD branch to here" command resethead}
+ {mc "Mark this commit" command markhere}
+ {mc "Return to mark" command gotomark}
+ {mc "Find descendant of this and mark" command find_common_desc}
+ {mc "Compare with marked commit" command compare_commits}
}
$rowctxmenu configure -tearoff 0
global maxwidth showneartags showlocalchanges
global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
global cmitmode wrapcomment datetimeformat limitdiffs
- global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
+ global colors uicolor bgcolor fgcolor diffcolors diffcontext selectbgcolor
global autoselect extdifftool perfile_attrs markbgcolor
+ global hideremotes
if {$stuffsaved} return
if {![winfo viewable .]} return
catch {
+ if {[file exists ~/.gitk-new]} {file delete -force ~/.gitk-new}
set f [open "~/.gitk-new" w]
+ if {$::tcl_platform(platform) eq {windows}} {
+ file attributes "~/.gitk-new" -hidden true
+ }
puts $f [list set mainfont $mainfont]
puts $f [list set textfont $textfont]
puts $f [list set uifont $uifont]
puts $f [list set wrapcomment $wrapcomment]
puts $f [list set autoselect $autoselect]
puts $f [list set showneartags $showneartags]
+ puts $f [list set hideremotes $hideremotes]
puts $f [list set showlocalchanges $showlocalchanges]
puts $f [list set datetimeformat $datetimeformat]
puts $f [list set limitdiffs $limitdiffs]
+ puts $f [list set uicolor $uicolor]
puts $f [list set bgcolor $bgcolor]
puts $f [list set fgcolor $fgcolor]
puts $f [list set colors $colors]
puts $f [list set perfile_attrs $perfile_attrs]
puts $f "set geometry(main) [wm geometry .]"
+ puts $f "set geometry(state) [wm state .]"
puts $f "set geometry(topwidth) [winfo width .tf]"
puts $f "set geometry(topheight) [winfo height .tf]"
puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
}
toplevel $w
wm title $w [mc "About gitk"]
+ make_transient $w .
message $w.m -text [mc "
Gitk - a commit viewer for git
}
toplevel $w
wm title $w [mc "Gitk key bindings"]
+ make_transient $w .
message $w.m -text "
[mc "Gitk key bindings:"]
[mc "<%s-F> Find" $M1T]
[mc "<%s-G> Move to next find hit" $M1T]
[mc "<Return> Move to next find hit"]
-[mc "/ Move to next find hit, or redo find"]
+[mc "/ Focus the search box"]
[mc "? Move to previous find hit"]
[mc "f Scroll diff view to next file"]
[mc "<%s-S> Search for next hit in diff view" $M1T]
-justify left -bg white -border 2 -relief groove
pack $w.m -side top -fill both -padx 2 -pady 2
button $w.ok -text [mc "Close"] -command "destroy $w" -default active
+ bind $w <Key-Escape> [list destroy $w]
pack $w.ok -side bottom
bind $w <Visibility> "focus $w.ok"
bind $w <Key-Escape> "destroy $w"
set gdttype [mc "touching paths:"]
}
+proc gitknewtmpdir {} {
+ global diffnum gitktmpdir gitdir
+
+ if {![info exists gitktmpdir]} {
+ set gitktmpdir [file join [file dirname $gitdir] \
+ [format ".gitk-tmp.%s" [pid]]]
+ if {[catch {file mkdir $gitktmpdir} err]} {
+ error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
+ unset gitktmpdir
+ return {}
+ }
+ set diffnum 0
+ }
+ incr diffnum
+ set diffdir [file join $gitktmpdir $diffnum]
+ if {[catch {file mkdir $diffdir} err]} {
+ error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
+ return {}
+ }
+ return $diffdir
+}
+
proc save_file_from_commit {filename output what} {
global nullfile
}
proc external_diff {} {
- global gitktmpdir nullid nullid2
+ global nullid nullid2
global flist_menu_file
global diffids
- global diffnum
- global gitdir extdifftool
+ global extdifftool
if {[llength $diffids] == 1} {
# no reference commit given
}
# make sure that several diffs wont collide
- if {![info exists gitktmpdir]} {
- set gitktmpdir [file join [file dirname $gitdir] \
- [format ".gitk-tmp.%s" [pid]]]
- if {[catch {file mkdir $gitktmpdir} err]} {
- error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
- unset gitktmpdir
- return
- }
- set diffnum 0
- }
- incr diffnum
- set diffdir [file join $gitktmpdir $diffnum]
- if {[catch {file mkdir $diffdir} err]} {
- error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
- return
- }
+ set diffdir [gitknewtmpdir]
+ if {$diffdir eq {}} return
# gather files to diff
set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
if {$difffromfile ne {} && $difftofile ne {}} {
- set cmd [concat | [shellsplit $extdifftool] \
- [list $difffromfile $difftofile]]
- if {[catch {set fl [open $cmd r]} err]} {
+ set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
+ if {[catch {set fl [open |$cmd r]} err]} {
file delete -force $diffdir
error_popup "$extdifftool: [mc "command failed:"] $err"
} else {
return {}
}
+# Turn an absolute path into one relative to the current directory
+proc make_relative {f} {
+ set elts [file split $f]
+ set here [file split [pwd]]
+ set ei 0
+ set hi 0
+ set res {}
+ foreach d $here {
+ if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
+ lappend res ".."
+ } else {
+ incr ei
+ }
+ incr hi
+ }
+ set elts [concat $res [lrange $elts $ei end]]
+ return [eval file join $elts]
+}
+
proc external_blame {parent_idx {line {}}} {
- global flist_menu_file
+ global flist_menu_file gitdir
global nullid nullid2
global parentlist selectedline currentid
if {$line ne {} && $line > 1} {
lappend cmdline "--line=$line"
}
- lappend cmdline $base_commit $flist_menu_file
+ set f [file join [file dirname $gitdir] $flist_menu_file]
+ # Unfortunately it seems git gui blame doesn't like
+ # being given an absolute path...
+ set f [make_relative $f]
+ lappend cmdline $base_commit $f
if {[catch {eval exec $cmdline &} err]} {
error_popup "[mc "git gui blame: command failed:"] $err"
}
error_popup [mc "Error reading index: %s" $err]
return
}
+ } else {
+ set id $parents($curview,$currentid)
}
} else {
set id [lindex $parents($curview,$currentid) $pi]
} else {
lappend blameargs $id
}
- lappend blameargs -- $flist_menu_file
+ lappend blameargs -- [file join [file dirname $gitdir] $flist_menu_file]
if {[catch {
set f [open $blameargs r]
} err]} {
error_popup [mc "Couldn't start git blame: %s" $err]
return
}
+ nowbusy blaming [mc "Searching"]
fconfigure $f -blocking 0
set i [reg_instance $f]
set blamestuff($i) {}
if {[info exists blameinst]} {
stop_instance $blameinst
unset blameinst
+ notbusy blaming
}
}
}
unset commfd($inst)
unset blameinst
+ notbusy blaming
fconfigure $fd -blocking 1
if {[catch {close $fd} err]} {
error_popup [mc "Error running git blame: %s" $err]
# Code to implement multiple views
proc newview {ishighlight} {
- global nextviewnum newviewname newviewperm newishighlight
- global newviewargs revtreeargs viewargscmd newviewargscmd curview
+ global nextviewnum newviewname newishighlight
+ global revtreeargs viewargscmd newviewopts curview
set newishighlight $ishighlight
set top .gitkview
return
}
set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
- set newviewperm($nextviewnum) 0
- set newviewargs($nextviewnum) [shellarglist $revtreeargs]
- set newviewargscmd($nextviewnum) $viewargscmd($curview)
+ set newviewopts($nextviewnum,perm) 0
+ set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
+ decode_view_opts $nextviewnum $revtreeargs
vieweditor $top $nextviewnum [mc "Gitk view definition"]
}
+set known_view_options {
+ {perm b . {} {mc "Remember this view"}}
+ {reflabel l + {} {mc "References (space separated list):"}}
+ {refs t15 .. {} {mc "Branches & tags:"}}
+ {allrefs b *. "--all" {mc "All refs"}}
+ {branches b . "--branches" {mc "All (local) branches"}}
+ {tags b . "--tags" {mc "All tags"}}
+ {remotes b . "--remotes" {mc "All remote-tracking branches"}}
+ {commitlbl l + {} {mc "Commit Info (regular expressions):"}}
+ {author t15 .. "--author=*" {mc "Author:"}}
+ {committer t15 . "--committer=*" {mc "Committer:"}}
+ {loginfo t15 .. "--grep=*" {mc "Commit Message:"}}
+ {allmatch b .. "--all-match" {mc "Matches all Commit Info criteria"}}
+ {changes_l l + {} {mc "Changes to Files:"}}
+ {pickaxe_s r0 . {} {mc "Fixed String"}}
+ {pickaxe_t r1 . "--pickaxe-regex" {mc "Regular Expression"}}
+ {pickaxe t15 .. "-S*" {mc "Search string:"}}
+ {datelabel l + {} {mc "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 15:27:38\"):"}}
+ {since t15 .. {"--since=*" "--after=*"} {mc "Since:"}}
+ {until t15 . {"--until=*" "--before=*"} {mc "Until:"}}
+ {limit_lbl l + {} {mc "Limit and/or skip a number of revisions (positive integer):"}}
+ {limit t10 *. "--max-count=*" {mc "Number to show:"}}
+ {skip t10 . "--skip=*" {mc "Number to skip:"}}
+ {misc_lbl l + {} {mc "Miscellaneous options:"}}
+ {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}}
+ {lright b . "--left-right" {mc "Mark branch sides"}}
+ {first b . "--first-parent" {mc "Limit to first parent"}}
+ {smplhst b . "--simplify-by-decoration" {mc "Simple history"}}
+ {args t50 *. {} {mc "Additional arguments to git log:"}}
+ {allpaths path + {} {mc "Enter files and directories to include, one per line:"}}
+ {cmd t50= + {} {mc "Command to generate more commits to include:"}}
+ }
+
+proc encode_view_opts {n} {
+ global known_view_options newviewopts
+
+ set rargs [list]
+ foreach opt $known_view_options {
+ set patterns [lindex $opt 3]
+ if {$patterns eq {}} continue
+ set pattern [lindex $patterns 0]
+
+ if {[lindex $opt 1] eq "b"} {
+ set val $newviewopts($n,[lindex $opt 0])
+ if {$val} {
+ lappend rargs $pattern
+ }
+ } elseif {[regexp {^r(\d+)$} [lindex $opt 1] type value]} {
+ regexp {^(.*_)} [lindex $opt 0] uselessvar button_id
+ set val $newviewopts($n,$button_id)
+ if {$val eq $value} {
+ lappend rargs $pattern
+ }
+ } else {
+ set val $newviewopts($n,[lindex $opt 0])
+ set val [string trim $val]
+ if {$val ne {}} {
+ set pfix [string range $pattern 0 end-1]
+ lappend rargs $pfix$val
+ }
+ }
+ }
+ set rargs [concat $rargs [shellsplit $newviewopts($n,refs)]]
+ return [concat $rargs [shellsplit $newviewopts($n,args)]]
+}
+
+proc decode_view_opts {n view_args} {
+ global known_view_options newviewopts
+
+ foreach opt $known_view_options {
+ set id [lindex $opt 0]
+ if {[lindex $opt 1] eq "b"} {
+ # Checkboxes
+ set val 0
+ } elseif {[regexp {^r(\d+)$} [lindex $opt 1]]} {
+ # Radiobuttons
+ regexp {^(.*_)} $id uselessvar id
+ set val 0
+ } else {
+ # Text fields
+ set val {}
+ }
+ set newviewopts($n,$id) $val
+ }
+ set oargs [list]
+ set refargs [list]
+ foreach arg $view_args {
+ if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
+ && ![info exists found(limit)]} {
+ set newviewopts($n,limit) $cnt
+ set found(limit) 1
+ continue
+ }
+ catch { unset val }
+ foreach opt $known_view_options {
+ set id [lindex $opt 0]
+ if {[info exists found($id)]} continue
+ foreach pattern [lindex $opt 3] {
+ if {![string match $pattern $arg]} continue
+ if {[lindex $opt 1] eq "b"} {
+ # Check buttons
+ set val 1
+ } elseif {[regexp {^r(\d+)$} [lindex $opt 1] match num]} {
+ # Radio buttons
+ regexp {^(.*_)} $id uselessvar id
+ set val $num
+ } else {
+ # Text input fields
+ set size [string length $pattern]
+ set val [string range $arg [expr {$size-1}] end]
+ }
+ set newviewopts($n,$id) $val
+ set found($id) 1
+ break
+ }
+ if {[info exists val]} break
+ }
+ if {[info exists val]} continue
+ if {[regexp {^-} $arg]} {
+ lappend oargs $arg
+ } else {
+ lappend refargs $arg
+ }
+ }
+ set newviewopts($n,refs) [shellarglist $refargs]
+ set newviewopts($n,args) [shellarglist $oargs]
+}
+
+proc edit_or_newview {} {
+ global curview
+
+ if {$curview > 0} {
+ editview
+ } else {
+ newview 0
+ }
+}
+
proc editview {} {
global curview
- global viewname viewperm newviewname newviewperm
- global viewargs newviewargs viewargscmd newviewargscmd
+ global viewname viewperm newviewname newviewopts
+ global viewargs viewargscmd
set top .gitkvedit-$curview
if {[winfo exists $top]} {
raise $top
return
}
- set newviewname($curview) $viewname($curview)
- set newviewperm($curview) $viewperm($curview)
- set newviewargs($curview) [shellarglist $viewargs($curview)]
- set newviewargscmd($curview) $viewargscmd($curview)
- vieweditor $top $curview "Gitk: edit view $viewname($curview)"
+ set newviewname($curview) $viewname($curview)
+ set newviewopts($curview,perm) $viewperm($curview)
+ set newviewopts($curview,cmd) $viewargscmd($curview)
+ decode_view_opts $curview $viewargs($curview)
+ vieweditor $top $curview "[mc "Gitk: edit view"] $viewname($curview)"
}
proc vieweditor {top n title} {
- global newviewname newviewperm viewfiles bgcolor
+ global newviewname newviewopts viewfiles bgcolor
+ global known_view_options
toplevel $top
- wm title $top $title
- label $top.nl -text [mc "Name"]
+ wm title $top [concat $title [mc "-- criteria for selecting revisions"]]
+ make_transient $top .
+
+ # View name
+ frame $top.nfr
+ label $top.nl -text [mc "View Name:"]
entry $top.name -width 20 -textvariable newviewname($n)
- grid $top.nl $top.name -sticky w -pady 5
- checkbutton $top.perm -text [mc "Remember this view"] \
- -variable newviewperm($n)
- grid $top.perm - -pady 5 -sticky w
- message $top.al -aspect 1000 \
- -text [mc "Commits to include (arguments to git log):"]
- grid $top.al - -sticky w -pady 5
- entry $top.args -width 50 -textvariable newviewargs($n) \
- -background $bgcolor
- grid $top.args - -sticky ew -padx 5
-
- message $top.ac -aspect 1000 \
- -text [mc "Command to generate more commits to include:"]
- grid $top.ac - -sticky w -pady 5
- entry $top.argscmd -width 50 -textvariable newviewargscmd($n) \
- -background white
- grid $top.argscmd - -sticky ew -padx 5
-
- message $top.l -aspect 1000 \
- -text [mc "Enter files and directories to include, one per line:"]
- grid $top.l - -sticky w
- text $top.t -width 40 -height 10 -background $bgcolor -font uifont
- if {[info exists viewfiles($n)]} {
- foreach f $viewfiles($n) {
- $top.t insert end $f
- $top.t insert end "\n"
- }
- $top.t delete {end - 1c} end
- $top.t mark set insert 0.0
- }
- grid $top.t - -sticky ew -padx 5
+ pack $top.nfr -in $top -fill x -pady 5 -padx 3
+ pack $top.nl -in $top.nfr -side left -padx {0 5}
+ pack $top.name -in $top.nfr -side left -padx {0 25}
+
+ # View options
+ set cframe $top.nfr
+ set cexpand 0
+ set cnt 0
+ foreach opt $known_view_options {
+ set id [lindex $opt 0]
+ set type [lindex $opt 1]
+ set flags [lindex $opt 2]
+ set title [eval [lindex $opt 4]]
+ set lxpad 0
+
+ if {$flags eq "+" || $flags eq "*"} {
+ set cframe $top.fr$cnt
+ incr cnt
+ frame $cframe
+ pack $cframe -in $top -fill x -pady 3 -padx 3
+ set cexpand [expr {$flags eq "*"}]
+ } elseif {$flags eq ".." || $flags eq "*."} {
+ set cframe $top.fr$cnt
+ incr cnt
+ frame $cframe
+ pack $cframe -in $top -fill x -pady 3 -padx [list 15 3]
+ set cexpand [expr {$flags eq "*."}]
+ } else {
+ set lxpad 5
+ }
+
+ if {$type eq "l"} {
+ label $cframe.l_$id -text $title
+ pack $cframe.l_$id -in $cframe -side left -pady [list 3 0] -anchor w
+ } elseif {$type eq "b"} {
+ checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
+ pack $cframe.c_$id -in $cframe -side left \
+ -padx [list $lxpad 0] -expand $cexpand -anchor w
+ } elseif {[regexp {^r(\d+)$} $type type sz]} {
+ regexp {^(.*_)} $id uselessvar button_id
+ radiobutton $cframe.c_$id -text $title -variable newviewopts($n,$button_id) -value $sz
+ pack $cframe.c_$id -in $cframe -side left \
+ -padx [list $lxpad 0] -expand $cexpand -anchor w
+ } elseif {[regexp {^t(\d+)$} $type type sz]} {
+ message $cframe.l_$id -aspect 1500 -text $title
+ entry $cframe.e_$id -width $sz -background $bgcolor \
+ -textvariable newviewopts($n,$id)
+ pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
+ pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
+ } elseif {[regexp {^t(\d+)=$} $type type sz]} {
+ message $cframe.l_$id -aspect 1500 -text $title
+ entry $cframe.e_$id -width $sz -background $bgcolor \
+ -textvariable newviewopts($n,$id)
+ pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
+ pack $cframe.e_$id -in $cframe -side top -fill x
+ } elseif {$type eq "path"} {
+ message $top.l -aspect 1500 -text $title
+ pack $top.l -in $top -side top -pady [list 3 0] -anchor w -padx 3
+ text $top.t -width 40 -height 5 -background $bgcolor -font uifont
+ if {[info exists viewfiles($n)]} {
+ foreach f $viewfiles($n) {
+ $top.t insert end $f
+ $top.t insert end "\n"
+ }
+ $top.t delete {end - 1c} end
+ $top.t mark set insert 0.0
+ }
+ pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
+ }
+ }
+
frame $top.buts
button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
+ button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
- grid $top.buts.ok $top.buts.can
+ bind $top <Control-Return> [list newviewok $top $n]
+ bind $top <F5> [list newviewok $top $n 1]
+ bind $top <Escape> [list destroy $top]
+ grid $top.buts.ok $top.buts.apply $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
- grid $top.buts - -pady 10 -sticky ew
+ grid columnconfigure $top.buts 2 -weight 1 -uniform a
+ pack $top.buts -in $top -side top -fill x
focus $top.t
}
# doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
}
-proc newviewok {top n} {
+proc newviewok {top n {apply 0}} {
global nextviewnum newviewperm newviewname newishighlight
global viewname viewfiles viewperm selectedview curview
- global viewargs newviewargs viewargscmd newviewargscmd viewhlmenu
+ global viewargs viewargscmd newviewopts viewhlmenu
if {[catch {
- set newargs [shellsplit $newviewargs($n)]
+ set newargs [encode_view_opts $n]
} err]} {
- error_popup "[mc "Error in commit selection arguments:"] $err"
- wm raise $top
- focus $top
+ error_popup "[mc "Error in commit selection arguments:"] $err" $top
return
}
set files {}
# creating a new view
incr nextviewnum
set viewname($n) $newviewname($n)
- set viewperm($n) $newviewperm($n)
+ set viewperm($n) $newviewopts($n,perm)
set viewfiles($n) $files
set viewargs($n) $newargs
- set viewargscmd($n) $newviewargscmd($n)
+ set viewargscmd($n) $newviewopts($n,cmd)
addviewmenu $n
if {!$newishighlight} {
run showview $n
}
} else {
# editing an existing view
- set viewperm($n) $newviewperm($n)
+ set viewperm($n) $newviewopts($n,perm)
if {$newviewname($n) ne $viewname($n)} {
set viewname($n) $newviewname($n)
doviewmenu .bar.view 5 [list showview $n] \
# entryconf [list -label $viewname($n) -value $viewname($n)]
}
if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
- $newviewargscmd($n) ne $viewargscmd($n)} {
+ $newviewopts($n,cmd) ne $viewargscmd($n)} {
set viewfiles($n) $files
set viewargs($n) $newargs
- set viewargscmd($n) $newviewargscmd($n)
+ set viewargscmd($n) $newviewopts($n,cmd)
if {$curview == $n} {
run reloadcommits
}
}
}
+ if {$apply} return
catch {destroy $top}
}
return 0
}
-proc bolden {row font} {
- global canv linehtag selectedline boldrows
+proc bolden {id font} {
+ global canv linehtag currentid boldids need_redisplay markedid
- lappend boldrows $row
- $canv itemconf $linehtag($row) -font $font
- if {$row == $selectedline} {
+ # need_redisplay = 1 means the display is stale and about to be redrawn
+ if {$need_redisplay} return
+ lappend boldids $id
+ $canv itemconf $linehtag($id) -font $font
+ if {[info exists currentid] && $id eq $currentid} {
$canv delete secsel
- set t [eval $canv create rect [$canv bbox $linehtag($row)] \
+ set t [eval $canv create rect [$canv bbox $linehtag($id)] \
-outline {{}} -tags secsel \
-fill [$canv cget -selectbackground]]
$canv lower $t
}
+ if {[info exists markedid] && $id eq $markedid} {
+ make_idmark $id
+ }
}
-proc bolden_name {row font} {
- global canv2 linentag selectedline boldnamerows
+proc bolden_name {id font} {
+ global canv2 linentag currentid boldnameids need_redisplay
- lappend boldnamerows $row
- $canv2 itemconf $linentag($row) -font $font
- if {$row == $selectedline} {
+ if {$need_redisplay} return
+ lappend boldnameids $id
+ $canv2 itemconf $linentag($id) -font $font
+ if {[info exists currentid] && $id eq $currentid} {
$canv2 delete secsel
- set t [eval $canv2 create rect [$canv2 bbox $linentag($row)] \
+ set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
-outline {{}} -tags secsel \
-fill [$canv2 cget -selectbackground]]
$canv2 lower $t
}
proc unbolden {} {
- global boldrows
+ global boldids
set stillbold {}
- foreach row $boldrows {
- if {![ishighlighted [commitonrow $row]]} {
- bolden $row mainfont
+ foreach id $boldids {
+ if {![ishighlighted $id]} {
+ bolden $id mainfont
} else {
- lappend stillbold $row
+ lappend stillbold $id
}
}
- set boldrows $stillbold
+ set boldids $stillbold
}
proc addvhighlight {n} {
set row [rowofcommit $id]
if {$r0 <= $row && $row <= $r1} {
if {![highlighted $row]} {
- bolden $row mainfontbold
+ bolden $id mainfontbold
}
set vhighlights($id) 1
}
if {[commitinview $id $hlview]} {
if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
- bolden $row mainfontbold
+ bolden $id mainfontbold
}
set vhighlights($id) 1
} else {
proc hfiles_change {} {
global highlight_files filehighlight fhighlights fh_serial
- global highlight_paths gdttype
+ global highlight_paths
if {[info exists filehighlight]} {
# delete previous highlights
}
proc findcom_change args {
- global nhighlights boldnamerows
+ global nhighlights boldnameids
global findpattern findtype findstring gdttype
stopfinding
# delete previous highlights, if any
- foreach row $boldnamerows {
- bolden_name $row mainfont
+ foreach id $boldnameids {
+ bolden_name $id mainfont
}
- set boldnamerows {}
+ set boldnameids {}
catch {unset nhighlights}
unbolden
unmarkmatches
set fhl_list [lrange $fhl_list [expr {$i+1}] end]
if {$line eq {}} continue
if {![commitinview $line $curview]} continue
- set row [rowofcommit $line]
if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
- bolden $row mainfontbold
+ bolden $line mainfontbold
}
set fhighlights($line) 1
}
}
if {$isbold && [info exists iddrawn($id)]} {
if {![ishighlighted $id]} {
- bolden $row mainfontbold
+ bolden $id mainfontbold
if {$isbold > 1} {
- bolden_name $row mainfontbold
+ bolden_name $id mainfontbold
}
}
if {$markingmatches} {
if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
set m [findmatches $headline]
if {$m ne {}} {
- markmatches $canv $row $headline $linehtag($row) $m \
- [$canv itemcget $linehtag($row) -font] $row
+ markmatches $canv $row $headline $linehtag($id) $m \
+ [$canv itemcget $linehtag($id) -font] $row
}
}
if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
set m [findmatches $author]
if {$m ne {}} {
- markmatches $canv2 $row $author $linentag($row) $m \
- [$canv2 itemcget $linentag($row) -font] $row
+ markmatches $canv2 $row $author $linentag($id) $m \
+ [$canv2 itemcget $linentag($id) -font] $row
}
}
}
}
if {[info exists iddrawn($id)]} {
if {$isbold && ![ishighlighted $id]} {
- bolden $row mainfontbold
+ bolden $id mainfontbold
}
}
set rhighlights($id) $isbold
drawvisible
}
+# With path limiting, we mightn't get the actual HEAD commit,
+# so ask git rev-list what is the first ancestor of HEAD that
+# touches a file in the path limit.
+proc get_viewmainhead {view} {
+ global viewmainheadid vfilelimit viewinstances mainheadid
+
+ catch {
+ set rfd [open [concat | git rev-list -1 $mainheadid \
+ -- $vfilelimit($view)] r]
+ set j [reg_instance $rfd]
+ lappend viewinstances($view) $j
+ fconfigure $rfd -blocking 0
+ filerun $rfd [list getviewhead $rfd $j $view]
+ set viewmainheadid($curview) {}
+ }
+}
+
+# git rev-list should give us just 1 line to use as viewmainheadid($view)
+proc getviewhead {fd inst view} {
+ global viewmainheadid commfd curview viewinstances showlocalchanges
+
+ set id {}
+ if {[gets $fd line] < 0} {
+ if {![eof $fd]} {
+ return 1
+ }
+ } elseif {[string length $line] == 40 && [string is xdigit $line]} {
+ set id $line
+ }
+ set viewmainheadid($view) $id
+ close $fd
+ unset commfd($inst)
+ set i [lsearch -exact $viewinstances($view) $inst]
+ if {$i >= 0} {
+ set viewinstances($view) [lreplace $viewinstances($view) $i $i]
+ }
+ if {$showlocalchanges && $id ne {} && $view == $curview} {
+ doshowlocalchanges
+ }
+ return 0
+}
+
proc doshowlocalchanges {} {
- global curview mainheadid
+ global curview viewmainheadid
- if {$mainheadid eq {}} return
- if {[commitinview $mainheadid $curview]} {
+ if {$viewmainheadid($curview) eq {}} return
+ if {[commitinview $viewmainheadid($curview) $curview]} {
dodiffindex
} else {
- interestedin $mainheadid dodiffindex
+ interestedin $viewmainheadid($curview) dodiffindex
}
}
# spawn off a process to do git diff-index --cached HEAD
proc dodiffindex {} {
- global lserial showlocalchanges
+ global lserial showlocalchanges vfilelimit curview
global isworktree
if {!$showlocalchanges || !$isworktree} return
incr lserial
- set fd [open "|git diff-index --cached HEAD" r]
+ set cmd "|git diff-index --cached HEAD"
+ if {$vfilelimit($curview) ne {}} {
+ set cmd [concat $cmd -- $vfilelimit($curview)]
+ }
+ set fd [open $cmd r]
fconfigure $fd -blocking 0
set i [reg_instance $fd]
filerun $fd [list readdiffindex $fd $lserial $i]
}
proc readdiffindex {fd serial inst} {
- global mainheadid nullid nullid2 curview commitinfo commitdata lserial
+ global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
+ global vfilelimit
set isdiff 1
if {[gets $fd line] < 0} {
}
# now see if there are any local changes not checked in to the index
- set fd [open "|git diff-files" r]
+ set cmd "|git diff-files"
+ if {$vfilelimit($curview) ne {}} {
+ set cmd [concat $cmd -- $vfilelimit($curview)]
+ }
+ set fd [open $cmd r]
fconfigure $fd -blocking 0
set i [reg_instance $fd]
filerun $fd [list readdifffiles $fd $serial $i]
if {[commitinview $nullid $curview]} {
removefakerow $nullid
}
- insertfakerow $nullid2 $mainheadid
+ insertfakerow $nullid2 $viewmainheadid($curview)
} elseif {!$isdiff && [commitinview $nullid2 $curview]} {
+ if {[commitinview $nullid $curview]} {
+ removefakerow $nullid
+ }
removefakerow $nullid2
}
return 0
}
proc readdifffiles {fd serial inst} {
- global mainheadid nullid nullid2 curview
+ global viewmainheadid nullid nullid2 curview
global commitinfo commitdata lserial
set isdiff 1
if {[commitinview $nullid2 $curview]} {
set p $nullid2
} else {
- set p $mainheadid
+ set p $viewmainheadid($curview)
}
insertfakerow $nullid $p
} elseif {!$isdiff && [commitinview $nullid $curview]} {
global cmitlisted commitinfo rowidlist parentlist
global rowtextx idpos idtags idheads idotherrefs
global linehtag linentag linedtag selectedline
- global canvxmax boldrows boldnamerows fgcolor
+ global canvxmax boldids boldnameids fgcolor markedid
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 nfont mainfont
set isbold [ishighlighted $id]
if {$isbold > 0} {
- lappend boldrows $row
+ lappend boldids $id
set font mainfontbold
if {$isbold > 1} {
- lappend boldnamerows $row
+ lappend boldnameids $id
set nfont mainfontbold
}
}
- set linehtag($row) [$canv create text $xt $y -anchor w -fill $fgcolor \
- -text $headline -font $font -tags text]
- $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 \
- -text $date -font mainfont -tags text]
+ set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
+ -text $headline -font $font -tags text]
+ $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
+ set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
+ -text $name -font $nfont -tags text]
+ set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
+ -text $date -font mainfont -tags text]
if {$selectedline == $row} {
- make_secsel $row
+ make_secsel $id
+ }
+ if {[info exists markedid] && $markedid eq $id} {
+ make_idmark $id
}
set xr [expr {$xt + [font measure $font $headline]}]
if {$xr > $canvxmax} {
optimize_rows $ro1 0 $r2
if {$need_redisplay || $nrows_drawn > 2000} {
clear_display
- drawvisible
}
# make the lines join to already-drawn rows either side
proc clear_display {} {
global iddrawn linesegs need_redisplay nrows_drawn
global vhighlights fhighlights nhighlights rhighlights
- global linehtag linentag linedtag boldrows boldnamerows
+ global linehtag linentag linedtag boldids boldnameids
allcanvs delete all
catch {unset iddrawn}
catch {unset linehtag}
catch {unset linentag}
catch {unset linedtag}
- set boldrows {}
- set boldnamerows {}
+ set boldids {}
+ set boldnameids {}
catch {unset vhighlights}
catch {unset fhighlights}
catch {unset nhighlights}
proc findselectline {l} {
global findloc commentend ctext findcurline markingmatches gdttype
- set markingmatches 1
+ set markingmatches [expr {$gdttype eq [mc "containing:"]}]
set findcurline $l
selectline $l 1
- if {$findloc == [mc "All fields"] || $findloc == [mc "Comments"]} {
+ if {$markingmatches &&
+ ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
# highlight the matches in the comments
set f [$ctext get 1.0 $commentend]
set matches [findmatches $f]
}
}
+proc appendshortlink {id {pre {}} {post {}}} {
+ global ctext linknum
+
+ $ctext insert end $pre
+ $ctext tag delete link$linknum
+ $ctext insert end [string range $id 0 7] link$linknum
+ $ctext insert end $post
+ setlink $id link$linknum
+ incr linknum
+}
+
proc makelink {id} {
global pendinglinks
}
}
if {[llength $tags] > $maxrefs} {
- $ctext insert $pos "many ([llength $tags])"
+ $ctext insert $pos "[mc "many"] ([llength $tags])"
} else {
set tags [lsort -index 0 -decreasing $tags]
set sep {}
}
}
-proc make_secsel {l} {
+proc make_secsel {id} {
global linehtag linentag linedtag canv canv2 canv3
- if {![info exists linehtag($l)]} return
+ if {![info exists linehtag($id)]} return
$canv delete secsel
- set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
+ set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
-tags secsel -fill [$canv cget -selectbackground]]
$canv lower $t
$canv2 delete secsel
- set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
+ set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
-tags secsel -fill [$canv2 cget -selectbackground]]
$canv2 lower $t
$canv3 delete secsel
- set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
+ set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
-tags secsel -fill [$canv3 cget -selectbackground]]
$canv3 lower $t
}
+proc make_idmark {id} {
+ global linehtag canv fgcolor
+
+ if {![info exists linehtag($id)]} return
+ $canv delete markid
+ set t [eval $canv create rect [$canv bbox $linehtag($id)] \
+ -tags markid -outline $fgcolor]
+ $canv raise $t
+}
+
proc selectline {l isnew {desired_loc {}}} {
global canv ctext commitinfo selectedline
global canvy0 linespc parents children curview
drawvisible
}
- make_secsel $l
+ make_secsel $id
if {$isnew} {
addtohistory [list selbyid $id]
set cmd [concat | git diff-index --cached $flags]
if {[llength $ids] > 1} {
# comparing index with specific revision
- if {$i == 0} {
+ if {$j == 0} {
lappend cmd -R [lindex $ids 1]
} else {
lappend cmd [lindex $ids 0]
set treediffs($ids) $treediff
}
unset treepending
- if {$cmitmode eq "tree"} {
+ if {$cmitmode eq "tree" && [llength $diffids] == 1} {
gettree $diffids
} elseif {$ids != $diffids} {
if {![info exists diffmergeid]} {
global diffcontextstring diffcontext
if {[string is integer -strict $diffcontextstring]} {
- if {$diffcontextstring > 0} {
+ if {$diffcontextstring >= 0} {
set diffcontext $diffcontextstring
reselectline
}
global ignorespace
global limitdiffs vfilelimit curview
global diffencoding targetline diffnparents
+ global git_version
- set cmd [diffcmd $ids "-p -C --cc --no-commit-id -U$diffcontext"]
+ set textconv {}
+ if {[package vcompare $git_version "1.6.1"] >= 0} {
+ set textconv "--textconv"
+ }
+ set submodule {}
+ if {[package vcompare $git_version "1.6.6"] >= 0} {
+ set submodule "--submodule"
+ }
+ set cmd [diffcmd $ids "-p $textconv $submodule -C --cc --no-commit-id -U$diffcontext"]
if {$ignorespace} {
append cmd " -w"
}
set diffnparents 0
set diffinhdr 0
set diffencoding [get_path_encoding {}]
- fconfigure $bdf -blocking 0 -encoding binary
+ fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
set blobdifffd($ids) $bdf
filerun $bdf [list getblobdiffline $bdf $diffids]
}
$ctext conf -state normal
while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
- close $bdf
+ catch {close $bdf}
return 0
}
if {![string compare -length 5 "diff " $line]} {
set diffnparents [expr {[string length $ats] - 1}]
set diffinhdr 0
+ } elseif {![string compare -length 10 "Submodule " $line]} {
+ # start of a new submodule
+ if {[string compare [$ctext get "end - 4c" end] "\n \n\n"]} {
+ $ctext insert end "\n"; # Add newline after commit message
+ }
+ set curdiffstart [$ctext index "end - 1c"]
+ lappend ctext_file_names ""
+ set fname [string range $line 10 [expr [string last " " $line] - 1]]
+ lappend ctext_file_lines $fname
+ makediffhdr $fname $ids
+ $ctext insert end "\n$line\n" filesep
+ } elseif {![string compare -length 3 " >" $line]} {
+ $ctext insert end "$line\n" dresult
+ } elseif {![string compare -length 3 " <" $line]} {
+ $ctext insert end "$line\n" d0
} elseif {$diffinhdr} {
if {![string compare -length 12 "rename from " $line]} {
set fname [string range $line [expr 6 + [string first " from " $line] ] end]
$ctext insert end "$line\n" filesep
} else {
- set line [encoding convertfrom $diffencoding $line]
+ set line [string map {\x1A ^Z} \
+ [encoding convertfrom $diffencoding $line]]
# parse the prefix - one ' ', '-' or '+' for each parent
set prefix [string range $line 0 [expr {$diffnparents - 1}]]
set tag [expr {$diffnparents > 1? "m": "d"}]
}
$ctext conf -state disabled
if {[eof $bdf]} {
- close $bdf
+ catch {close $bdf}
return 0
}
return [expr {$nr >= 1000? 2: 1}]
}
set id [lindex $matches 0]
}
+ } else {
+ if {[catch {set id [exec git rev-parse --verify $sha1string]}]} {
+ error_popup [mc "Revision %s is not known" $sha1string]
+ return
+ }
}
}
if {[commitinview $id $curview]} {
if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
set msg [mc "SHA1 id %s is not known" $sha1string]
} else {
- set msg [mc "Tag/Head %s is not known" $sha1string]
+ set msg [mc "Revision %s is not in the current view" $sha1string]
}
error_popup $msg
}
proc rowmenu {x y id} {
global rowctxmenu selectedline rowmenuid curview
- global nullid nullid2 fakerowmenu mainhead
+ global nullid nullid2 fakerowmenu mainhead markedid
stopfinding
set rowmenuid $id
if {$id ne $nullid && $id ne $nullid2} {
set menu $rowctxmenu
if {$mainhead ne {}} {
- $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead]
+ $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead] -state normal
} else {
$menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
}
+ if {[info exists markedid] && $markedid ne $id} {
+ $menu entryconfigure 9 -state normal
+ $menu entryconfigure 10 -state normal
+ $menu entryconfigure 11 -state normal
+ } else {
+ $menu entryconfigure 9 -state disabled
+ $menu entryconfigure 10 -state disabled
+ $menu entryconfigure 11 -state disabled
+ }
} else {
set menu $fakerowmenu
}
tk_popup $menu $x $y
}
+proc markhere {} {
+ global rowmenuid markedid canv
+
+ set markedid $rowmenuid
+ make_idmark $markedid
+}
+
+proc gotomark {} {
+ global markedid
+
+ if {[info exists markedid]} {
+ selbyid $markedid
+ }
+}
+
+proc replace_by_kids {l r} {
+ global curview children
+
+ set id [commitonrow $r]
+ set l [lreplace $l 0 0]
+ foreach kid $children($curview,$id) {
+ lappend l [rowofcommit $kid]
+ }
+ return [lsort -integer -decreasing -unique $l]
+}
+
+proc find_common_desc {} {
+ global markedid rowmenuid curview children
+
+ if {![info exists markedid]} return
+ if {![commitinview $markedid $curview] ||
+ ![commitinview $rowmenuid $curview]} return
+ #set t1 [clock clicks -milliseconds]
+ set l1 [list [rowofcommit $markedid]]
+ set l2 [list [rowofcommit $rowmenuid]]
+ while 1 {
+ set r1 [lindex $l1 0]
+ set r2 [lindex $l2 0]
+ if {$r1 eq {} || $r2 eq {}} break
+ if {$r1 == $r2} {
+ selectline $r1 1
+ break
+ }
+ if {$r1 > $r2} {
+ set l1 [replace_by_kids $l1 $r1]
+ } else {
+ set l2 [replace_by_kids $l2 $r2]
+ }
+ }
+ #set t2 [clock clicks -milliseconds]
+ #puts "took [expr {$t2-$t1}]ms"
+}
+
+proc compare_commits {} {
+ global markedid rowmenuid curview children
+
+ if {![info exists markedid]} return
+ if {![commitinview $markedid $curview]} return
+ addtohistory [list do_cmp_commits $markedid $rowmenuid]
+ do_cmp_commits $markedid $rowmenuid
+}
+
+proc getpatchid {id} {
+ global patchids
+
+ if {![info exists patchids($id)]} {
+ set cmd [diffcmd [list $id] {-p --root}]
+ # trim off the initial "|"
+ set cmd [lrange $cmd 1 end]
+ if {[catch {
+ set x [eval exec $cmd | git patch-id]
+ set patchids($id) [lindex $x 0]
+ }]} {
+ set patchids($id) "error"
+ }
+ }
+ return $patchids($id)
+}
+
+proc do_cmp_commits {a b} {
+ global ctext curview parents children patchids commitinfo
+
+ $ctext conf -state normal
+ clear_ctext
+ init_flist {}
+ for {set i 0} {$i < 100} {incr i} {
+ set skipa 0
+ set skipb 0
+ if {[llength $parents($curview,$a)] > 1} {
+ appendshortlink $a [mc "Skipping merge commit "] "\n"
+ set skipa 1
+ } else {
+ set patcha [getpatchid $a]
+ }
+ if {[llength $parents($curview,$b)] > 1} {
+ appendshortlink $b [mc "Skipping merge commit "] "\n"
+ set skipb 1
+ } else {
+ set patchb [getpatchid $b]
+ }
+ if {!$skipa && !$skipb} {
+ set heada [lindex $commitinfo($a) 0]
+ set headb [lindex $commitinfo($b) 0]
+ if {$patcha eq "error"} {
+ appendshortlink $a [mc "Error getting patch ID for "] \
+ [mc " - stopping\n"]
+ break
+ }
+ if {$patchb eq "error"} {
+ appendshortlink $b [mc "Error getting patch ID for "] \
+ [mc " - stopping\n"]
+ break
+ }
+ if {$patcha eq $patchb} {
+ if {$heada eq $headb} {
+ appendshortlink $a [mc "Commit "]
+ appendshortlink $b " == " " $heada\n"
+ } else {
+ appendshortlink $a [mc "Commit "] " $heada\n"
+ appendshortlink $b [mc " is the same patch as\n "] \
+ " $headb\n"
+ }
+ set skipa 1
+ set skipb 1
+ } else {
+ $ctext insert end "\n"
+ appendshortlink $a [mc "Commit "] " $heada\n"
+ appendshortlink $b [mc " differs from\n "] \
+ " $headb\n"
+ $ctext insert end [mc "Diff of commits:\n\n"]
+ $ctext conf -state disabled
+ update
+ diffcommits $a $b
+ return
+ }
+ }
+ if {$skipa} {
+ if {[llength $children($curview,$a)] != 1} {
+ $ctext insert end "\n"
+ appendshortlink $a [mc "Commit "] \
+ [mc " has %s children - stopping\n" \
+ [llength $children($curview,$a)]]
+ break
+ }
+ set a [lindex $children($curview,$a) 0]
+ }
+ if {$skipb} {
+ if {[llength $children($curview,$b)] != 1} {
+ appendshortlink $b [mc "Commit "] \
+ [mc " has %s children - stopping\n" \
+ [llength $children($curview,$b)]]
+ break
+ }
+ set b [lindex $children($curview,$b) 0]
+ }
+ }
+ $ctext conf -state disabled
+}
+
+proc diffcommits {a b} {
+ global diffcontext diffids blobdifffd diffinhdr
+
+ set tmpdir [gitknewtmpdir]
+ set fna [file join $tmpdir "commit-[string range $a 0 7]"]
+ set fnb [file join $tmpdir "commit-[string range $b 0 7]"]
+ if {[catch {
+ exec git diff-tree -p --pretty $a >$fna
+ exec git diff-tree -p --pretty $b >$fnb
+ } err]} {
+ error_popup [mc "Error writing commit to file: %s" $err]
+ return
+ }
+ if {[catch {
+ set fd [open "| diff -U$diffcontext $fna $fnb" r]
+ } err]} {
+ error_popup [mc "Error diffing commits: %s" $err]
+ return
+ }
+ set diffids [list commits $a $b]
+ set blobdifffd($diffids) $fd
+ set diffinhdr 0
+ filerun $fd [list getblobdiffline $fd $diffids]
+}
+
proc diffvssel {dirn} {
global rowmenuid selectedline
set patchtop $top
catch {destroy $top}
toplevel $top
+ make_transient $top .
label $top.title -text [mc "Generate patch"]
grid $top.title - -pady 10
label $top.from -text [mc "From:"]
frame $top.buts
button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
+ bind $top <Key-Return> mkpatchgo
+ bind $top <Key-Escape> mkpatchcan
grid $top.buts.gen $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
set cmd [lrange $cmd 1 end]
lappend cmd >$fname &
if {[catch {eval exec $cmd} err]} {
- error_popup "[mc "Error creating patch:"] $err"
+ error_popup "[mc "Error creating patch:"] $err" $patchtop
}
catch {destroy $patchtop}
unset patchtop
set mktagtop $top
catch {destroy $top}
toplevel $top
+ make_transient $top .
label $top.title -text [mc "Create tag"]
grid $top.title - -pady 10
label $top.id -text [mc "ID:"]
frame $top.buts
button $top.buts.gen -text [mc "Create"] -command mktaggo
button $top.buts.can -text [mc "Cancel"] -command mktagcan
+ bind $top <Key-Return> mktaggo
+ bind $top <Key-Escape> mktagcan
grid $top.buts.gen $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
set id [$mktagtop.sha1 get]
set tag [$mktagtop.tag get]
if {$tag == {}} {
- error_popup [mc "No tag name specified"]
- return
+ error_popup [mc "No tag name specified"] $mktagtop
+ return 0
}
if {[info exists tagids($tag)]} {
- error_popup [mc "Tag \"%s\" already exists" $tag]
- return
+ error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
+ return 0
}
if {[catch {
exec git tag $tag $id
} err]} {
- error_popup "[mc "Error creating tag:"] $err"
- return
+ error_popup "[mc "Error creating tag:"] $err" $mktagtop
+ return 0
}
set tagids($tag) $id
addedtag $id
dispneartags 0
run refill_reflist
+ return 1
}
proc redrawtags {id} {
- global canv linehtag idpos currentid curview cmitlisted
+ global canv linehtag idpos currentid curview cmitlisted markedid
global canvxmax iddrawn circleitem mainheadid circlecolors
if {![commitinview $id $curview]} return
$canv itemconf $circleitem($row) -fill $ofill
$canv delete tag.$id
set xt [eval drawtags $id $idpos($id)]
- $canv coords $linehtag($row) $xt [lindex $idpos($id) 2]
- set text [$canv itemcget $linehtag($row) -text]
- set font [$canv itemcget $linehtag($row) -font]
+ $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
+ set text [$canv itemcget $linehtag($id) -text]
+ set font [$canv itemcget $linehtag($id) -font]
set xr [expr {$xt + [font measure $font $text]}]
if {$xr > $canvxmax} {
set canvxmax $xr
setcanvscroll
}
if {[info exists currentid] && $currentid == $id} {
- make_secsel $row
+ make_secsel $id
+ }
+ if {[info exists markedid] && $markedid eq $id} {
+ make_idmark $id
}
}
}
proc mktaggo {} {
- domktag
+ if {![domktag]} return
mktagcan
}
set wrcomtop $top
catch {destroy $top}
toplevel $top
+ make_transient $top .
label $top.title -text [mc "Write commit to file"]
grid $top.title - -pady 10
label $top.id -text [mc "ID:"]
frame $top.buts
button $top.buts.gen -text [mc "Write"] -command wrcomgo
button $top.buts.can -text [mc "Cancel"] -command wrcomcan
+ bind $top <Key-Return> wrcomgo
+ bind $top <Key-Escape> wrcomcan
grid $top.buts.gen $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
set cmd "echo $id | [$wrcomtop.cmd get]"
set fname [$wrcomtop.fname get]
if {[catch {exec sh -c $cmd >$fname &} err]} {
- error_popup "[mc "Error writing commit:"] $err"
+ error_popup "[mc "Error writing commit:"] $err" $wrcomtop
}
catch {destroy $wrcomtop}
unset wrcomtop
set top .makebranch
catch {destroy $top}
toplevel $top
+ make_transient $top .
label $top.title -text [mc "Create new branch"]
grid $top.title - -pady 10
label $top.id -text [mc "ID:"]
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]
button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
+ bind $top <Key-Return> [list mkbrgo $top]
+ bind $top <Key-Escape> "catch {destroy $top}"
grid $top.buts.go $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
set cmdargs {}
set old_id {}
if {$name eq {}} {
- error_popup [mc "Please specify a name for the new branch"]
+ error_popup [mc "Please specify a name for the new branch"] $top
return
}
if {[info exists headids($name)]} {
if {![confirm_popup [mc \
- "Branch '%s' already exists. Overwrite?" $name]]} {
+ "Branch '%s' already exists. Overwrite?" $name] $top]} {
return
}
set old_id $headids($name)
}
}
+proc exec_citool {tool_args {baseid {}}} {
+ global commitinfo env
+
+ set save_env [array get env GIT_AUTHOR_*]
+
+ if {$baseid ne {}} {
+ if {![info exists commitinfo($baseid)]} {
+ getcommit $baseid
+ }
+ set author [lindex $commitinfo($baseid) 1]
+ set date [lindex $commitinfo($baseid) 2]
+ if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
+ $author author name email]
+ && $date ne {}} {
+ set env(GIT_AUTHOR_NAME) $name
+ set env(GIT_AUTHOR_EMAIL) $email
+ set env(GIT_AUTHOR_DATE) $date
+ }
+ }
+
+ eval exec git citool $tool_args &
+
+ array unset env GIT_AUTHOR_*
+ array set env $save_env
+}
+
proc cherrypick {} {
global rowmenuid curview
global mainhead mainheadid
# no error occurs, and exec takes that as an indication of error...
if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
notbusy cherrypick
- error_popup $err
+ if {[regexp -line \
+ {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
+ $err msg fname]} {
+ error_popup [mc "Cherry-pick failed because of local changes\
+ to file '%s'.\nPlease commit, reset or stash\
+ your changes and try again." $fname]
+ } elseif {[regexp -line \
+ {^(CONFLICT \(.*\):|Automatic cherry-pick failed)} \
+ $err]} {
+ if {[confirm_popup [mc "Cherry-pick failed because of merge\
+ conflict.\nDo you wish to run git citool to\
+ resolve it?"]]} {
+ # Force citool to read MERGE_MSG
+ file delete [file join [gitdir] "GITGUI_MSG"]
+ exec_citool {} $rowmenuid
+ }
+ } else {
+ error_popup $err
+ }
+ run updatecommits
return
}
set newhead [exec git rev-parse HEAD]
}
addnewchild $newhead $oldhead
if {[commitinview $oldhead $curview]} {
+ # XXX this isn't right if we have a path limit...
insertrow $newhead $oldhead $curview
if {$mainhead ne {}} {
movehead $newhead $mainhead
set confirm_ok 0
set w ".confirmreset"
toplevel $w
- wm transient $w .
+ make_transient $w .
wm title $w [mc "Confirm reset"]
message $w.m -text \
[mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]] \
button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
pack $w.ok -side left -fill x -padx 20 -pady 20
button $w.cancel -text [mc Cancel] -command "destroy $w"
+ bind $w <Key-Escape> [list destroy $w]
pack $w.cancel -side right -fill x -padx 20 -pady 20
bind $w <Visibility> "grab $w; focus $w"
tkwait window $w
proc cobranch {} {
global headmenuid headmenuhead headids
- global showlocalchanges mainheadid
+ global showlocalchanges
# check the tree is clean first??
nowbusy checkout [mc "Checking out"]
proc readcheckoutstat {fd newhead newheadid} {
global mainhead mainheadid headids showlocalchanges progresscoords
+ global viewmainheadid curview
if {[gets $fd line] >= 0} {
if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
set oldmainid $mainheadid
set mainhead $newhead
set mainheadid $newheadid
+ set viewmainheadid($curview) $newheadid
redrawtags $oldmainid
redrawtags $newheadid
selbyid $newheadid
}
toplevel $top
wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
+ make_transient $top .
text $top.list -background $bgcolor -foreground $fgcolor \
-selectbackground $selectbgcolor -font mainfont \
-xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
pack $top.f.l -side left
grid $top.f - -sticky ew -pady 2
button $top.close -command [list destroy $top] -text [mc "Close"]
+ bind $top <Key-Escape> [list destroy $top]
grid $top.close -
grid columnconfigure $top 0 -weight 1
grid rowconfigure $top 0 -weight 1
proc choosefont {font which} {
global fontparam fontlist fonttop fontattr
+ global prefstop
set fontparam(which) $which
set fontparam(font) $font
font create sample
eval font config sample [font actual $font]
toplevel $top
+ make_transient $top $prefstop
wm title $top [mc "Gitk font chooser"]
label $top.l -textvariable fontparam(which)
pack $top.l -side top
frame $top.buts
button $top.buts.ok -text [mc "OK"] -command fontok -default active
button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
+ bind $top <Key-Return> fontok
+ bind $top <Key-Escape> fontcan
grid $top.buts.ok $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
proc doprefs {} {
global maxwidth maxgraphpct
global oldprefs prefstop showneartags showlocalchanges
- global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
+ global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
global tabstop limitdiffs autoselect extdifftool perfile_attrs
+ global hideremotes
set top .gitkprefs
set prefstop $top
return
}
foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
- limitdiffs tabstop perfile_attrs} {
+ limitdiffs tabstop perfile_attrs hideremotes} {
set oldprefs($v) [set $v]
}
toplevel $top
wm title $top [mc "Gitk preferences"]
+ make_transient $top .
label $top.ldisp -text [mc "Commit list display options"]
grid $top.ldisp - -sticky w -pady 10
label $top.spacer -text " "
-font optionfont
spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
grid x $top.maxpctl $top.maxpct -sticky w
- frame $top.showlocal
- label $top.showlocal.l -text [mc "Show local changes"] -font optionfont
- checkbutton $top.showlocal.b -variable showlocalchanges
- pack $top.showlocal.b $top.showlocal.l -side left
+ checkbutton $top.showlocal -text [mc "Show local changes"] \
+ -font optionfont -variable showlocalchanges
grid x $top.showlocal -sticky w
- frame $top.autoselect
- label $top.autoselect.l -text [mc "Auto-select SHA1"] -font optionfont
- checkbutton $top.autoselect.b -variable autoselect
- pack $top.autoselect.b $top.autoselect.l -side left
+ checkbutton $top.autoselect -text [mc "Auto-select SHA1"] \
+ -font optionfont -variable autoselect
grid x $top.autoselect -sticky w
label $top.ddisp -text [mc "Diff display options"]
label $top.tabstopl -text [mc "Tab spacing"] -font optionfont
spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
grid x $top.tabstopl $top.tabstop -sticky w
- frame $top.ntag
- label $top.ntag.l -text [mc "Display nearby tags"] -font optionfont
- checkbutton $top.ntag.b -variable showneartags
- pack $top.ntag.b $top.ntag.l -side left
+ checkbutton $top.ntag -text [mc "Display nearby tags"] \
+ -font optionfont -variable showneartags
grid x $top.ntag -sticky w
- frame $top.ldiff
- label $top.ldiff.l -text [mc "Limit diffs to listed paths"] -font optionfont
- checkbutton $top.ldiff.b -variable limitdiffs
- pack $top.ldiff.b $top.ldiff.l -side left
+ checkbutton $top.hideremotes -text [mc "Hide remote refs"] \
+ -font optionfont -variable hideremotes
+ grid x $top.hideremotes -sticky w
+ checkbutton $top.ldiff -text [mc "Limit diffs to listed paths"] \
+ -font optionfont -variable limitdiffs
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
+ checkbutton $top.lattr -text [mc "Support per-file encodings"] \
+ -font optionfont -variable perfile_attrs
grid x $top.lattr -sticky w
entry $top.extdifft -textvariable extdifftool
label $top.cdisp -text [mc "Colors: press to choose"]
grid $top.cdisp - -sticky w -pady 10
+ label $top.ui -padx 40 -relief sunk -background $uicolor
+ button $top.uibut -text [mc "Interface"] -font optionfont \
+ -command [list choosecolor uicolor {} $top.ui [mc "interface"] setui]
+ grid x $top.uibut $top.ui -sticky w
label $top.bg -padx 40 -relief sunk -background $bgcolor
button $top.bgbut -text [mc "Background"] -font optionfont \
- -command [list choosecolor bgcolor {} $top.bg background setbg]
+ -command [list choosecolor bgcolor {} $top.bg [mc "background"] setbg]
grid x $top.bgbut $top.bg -sticky w
label $top.fg -padx 40 -relief sunk -background $fgcolor
button $top.fgbut -text [mc "Foreground"] -font optionfont \
- -command [list choosecolor fgcolor {} $top.fg foreground setfg]
+ -command [list choosecolor fgcolor {} $top.fg [mc "foreground"] setfg]
grid x $top.fgbut $top.fg -sticky w
label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
button $top.diffoldbut -text [mc "Diff: old lines"] -font optionfont \
- -command [list choosecolor diffcolors 0 $top.diffold "diff old lines" \
+ -command [list choosecolor diffcolors 0 $top.diffold [mc "diff old lines"] \
[list $ctext tag conf d0 -foreground]]
grid x $top.diffoldbut $top.diffold -sticky w
label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
button $top.diffnewbut -text [mc "Diff: new lines"] -font optionfont \
- -command [list choosecolor diffcolors 1 $top.diffnew "diff new lines" \
+ -command [list choosecolor diffcolors 1 $top.diffnew [mc "diff new lines"] \
[list $ctext tag conf dresult -foreground]]
grid x $top.diffnewbut $top.diffnew -sticky w
label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
button $top.hunksepbut -text [mc "Diff: hunk header"] -font optionfont \
-command [list choosecolor diffcolors 2 $top.hunksep \
- "diff hunk header" \
+ [mc "diff hunk header"] \
[list $ctext tag conf hunksep -foreground]]
grid x $top.hunksepbut $top.hunksep -sticky w
label $top.markbgsep -padx 40 -relief sunk -background $markbgcolor
grid x $top.markbgbut $top.markbgsep -sticky w
label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
button $top.selbgbut -text [mc "Select bg"] -font optionfont \
- -command [list choosecolor selectbgcolor {} $top.selbgsep background setselbg]
+ -command [list choosecolor selectbgcolor {} $top.selbgsep [mc "background"] setselbg]
grid x $top.selbgbut $top.selbgsep -sticky w
label $top.cfont -text [mc "Fonts: press to choose"]
frame $top.buts
button $top.buts.ok -text [mc "OK"] -command prefsok -default active
button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
+ bind $top <Key-Return> prefsok
+ bind $top <Key-Escape> prefscan
grid $top.buts.ok $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
proc choose_extdiff {} {
global extdifftool
- set prog [tk_getOpenFile -title "External diff tool" -multiple false]
+ set prog [tk_getOpenFile -title [mc "External diff tool"] -multiple false]
if {$prog ne {}} {
set extdifftool $prog
}
allcanvs itemconf secsel -fill $c
}
+proc setui {c} {
+ tk_setPalette $c
+}
+
proc setbg {c} {
global bglist
}
allcanvs itemconf text -fill $c
$canv itemconf circle -outline $c
+ $canv itemconf markid -outline $c
}
proc prefscan {} {
global oldprefs prefstop
foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
- limitdiffs tabstop perfile_attrs} {
+ limitdiffs tabstop perfile_attrs hideremotes} {
global $v
set $v $oldprefs($v)
}
global oldprefs prefstop showneartags showlocalchanges
global fontpref mainfont textfont uifont
global limitdiffs treediffs perfile_attrs
+ global hideremotes
catch {destroy $prefstop}
unset prefstop
$limitdiffs != $oldprefs(limitdiffs)} {
reselectline
}
+ if {$hideremotes != $oldprefs(hideremotes)} {
+ rereadrefs
+ }
}
proc formatdate {d} {
} else {
set r "unspecified"
if {![catch {set line [exec git check-attr $attr -- $path]}]} {
- regexp "(.*): encoding: (.*)" $line m f r
+ regexp "(.*): $attr: (.*)" $line m f r
}
set path_attr_cache($attr,$path) $r
}
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 {[regexp "(.*): $attr: (.*)" $row m path value]} {
if {[string index $path 0] eq "\""} {
set path [encoding convertfrom [lindex $path 0]]
}
# First check that Tcl/Tk is recent enough
if {[catch {package require Tk 8.4} err]} {
- show_error {} . [mc "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
- Gitk requires at least Tcl/Tk 8.4."]
+ show_error {} . "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
+ Gitk requires at least Tcl/Tk 8.4." list
exit 1
}
catch {
set gitencoding [exec git config --get i18n.commitencoding]
}
+catch {
+ set gitencoding [exec git config --get i18n.logoutputencoding]
+}
if {$gitencoding == ""} {
set gitencoding "utf-8"
}
}
}
-set mainfont {Helvetica 9}
-set textfont {Courier 9}
-set uifont {Helvetica 9 bold}
+if {[tk windowingsystem] eq "aqua"} {
+ set mainfont {{Lucida Grande} 9}
+ set textfont {Monaco 9}
+ set uifont {{Lucida Grande} 9 bold}
+} else {
+ set mainfont {Helvetica 9}
+ set textfont {Courier 9}
+ set uifont {Helvetica 9 bold}
+}
set tabstop 8
set findmergefiles 0
set maxgraphpct 50
set cmitmode "patch"
set wrapcomment "none"
set showneartags 1
+set hideremotes 0
set maxrefs 20
set maxlinelen 200
set showlocalchanges 1
set autoselect 1
set perfile_attrs 0
-set extdifftool "meld"
+if {[tk windowingsystem] eq "aqua"} {
+ set extdifftool "opendiff"
+} else {
+ set extdifftool "meld"
+}
set colors {green red blue magenta darkgrey brown orange}
+set uicolor grey85
set bgcolor white
set fgcolor black
set diffcolors {red "#00a000" blue}
parsefont uifont $uifont
eval font create uifont [fontflags uifont]
+tk_setPalette $uicolor
+
setoptions
# check that we can find a .git directory somewhere...
set nullfile "/dev/null"
set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
+set git_version [join [lrange [split [lindex [exec git version] end] .] 0 2] .]
set runq {}
set history {}
set highlight_paths {}
set findpattern {}
set searchdirn -forwards
-set boldrows {}
-set boldnamerows {}
+set boldids {}
+set boldnameids {}
set diffelide {0 0}
set markingmatches 0
set linkentercount 0
set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
setcoords
makewindow
+catch {
+ image create photo gitlogo -width 16 -height 16
+
+ image create photo gitlogominus -width 4 -height 2
+ gitlogominus put #C00000 -to 0 0 4 2
+ gitlogo copy gitlogominus -to 1 5
+ gitlogo copy gitlogominus -to 6 5
+ gitlogo copy gitlogominus -to 11 5
+ image delete gitlogominus
+
+ image create photo gitlogoplus -width 4 -height 4
+ gitlogoplus put #008000 -to 1 0 3 4
+ gitlogoplus put #008000 -to 0 1 4 3
+ gitlogo copy gitlogoplus -to 1 9
+ gitlogo copy gitlogoplus -to 6 9
+ gitlogo copy gitlogoplus -to 11 9
+ image delete gitlogoplus
+
+ image create photo gitlogo32 -width 32 -height 32
+ gitlogo32 copy gitlogo -zoom 2 2
+
+ wm iconphoto . -default gitlogo gitlogo32
+}
# wait for the window to become visible
tkwait visibility .
wm title . "[file tail $argv0]: [file tail [pwd]]"
+update
readrefs
if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
addviewmenu $n
}
}
+
+if {[tk windowingsystem] eq "win32"} {
+ focus -force .
+}
+
getcommits {}