if {[info exists env(GIT_DIR)]} {
return $env(GIT_DIR)
} else {
- return ".git"
+ return [exec git rev-parse --git-dir]
}
}
proc start_rev_list {view} {
- global startmsecs nextupdate ncmupdate
+ global startmsecs nextupdate
global commfd leftover tclencoding datemode
global viewargs viewfiles commitidx
set startmsecs [clock clicks -milliseconds]
set nextupdate [expr {$startmsecs + 100}]
- set ncmupdate 1
set commitidx($view) 0
set args $viewargs($view)
if {$viewfiles($view) ne {}} {
global parentlist childlist children curview hlview
global vparentlist vchildlist vdisporder vcmitlisted
- set stuff [read $fd]
+ set stuff [read $fd 500000]
if {$stuff == {}} {
if {![eof $fd]} return
global viewname
}
if {$gotsome} {
if {$view == $curview} {
- layoutmore
+ while {[layoutmore $nextupdate]} doupdate
} elseif {[info exists hlview] && $view == $hlview} {
vhighlightmore
}
}
proc doupdate {} {
- global commfd nextupdate numcommits ncmupdate
+ global commfd nextupdate numcommits
foreach v [array names commfd] {
fileevent $commfd($v) readable {}
}
update
set nextupdate [expr {[clock clicks -milliseconds] + 100}]
- if {$numcommits < 100} {
- set ncmupdate [expr {$numcommits + 1}]
- } elseif {$numcommits < 10000} {
- set ncmupdate [expr {$numcommits + 10}]
- } else {
- set ncmupdate [expr {$numcommits + 100}]
- }
foreach v [array names commfd] {
set fd $commfd($v)
fileevent $fd readable [list getcommitlines $fd $v]
foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
catch {unset $v}
}
- set refd [open [list | git ls-remote [gitdir]] r]
+ set refd [open [list | git show-ref] r]
while {0 <= [set n [gets $refd line]]} {
- if {![regexp {^([0-9a-f]{40}) refs/([^^]*)$} $line \
+ if {![regexp {^([0-9a-f]{40}) refs/([^^]*)$} $line \
match id path]} {
continue
}
.bar.view add separator
.bar.view add radiobutton -label "All files" -command {showview 0} \
-variable selectedview -value 0
-
+
menu .bar.help
.bar add cascade -label "Help" -menu .bar.help
.bar.help add command -label "About gitk" -command about
.bar.help configure -font $uifont
. configure -menu .bar
- if {![info exists geometry(canv1)]} {
- set geometry(canv1) [expr {45 * $charspc}]
- set geometry(canv2) [expr {30 * $charspc}]
- set geometry(canv3) [expr {15 * $charspc}]
- set geometry(canvh) [expr {25 * $linespc + 4}]
- set geometry(ctextw) 80
- set geometry(ctexth) 30
- set geometry(cflistw) 30
- }
+ # the gui has upper and lower half, parts of a paned window.
panedwindow .ctop -orient vertical
- if {[info exists geometry(width)]} {
- .ctop conf -width $geometry(width) -height $geometry(height)
- set texth [expr {$geometry(height) - $geometry(canvh) - 56}]
- set geometry(ctexth) [expr {($texth - 8) /
- [font metrics $textfont -linespace]}]
- }
- frame .ctop.top
- frame .ctop.top.bar
- frame .ctop.top.lbar
- pack .ctop.top.lbar -side bottom -fill x
- pack .ctop.top.bar -side bottom -fill x
- set cscroll .ctop.top.csb
- scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
- pack $cscroll -side right -fill y
- panedwindow .ctop.top.clist -orient horizontal -sashpad 0 -handlesize 4
- pack .ctop.top.clist -side top -fill both -expand 1
- .ctop add .ctop.top
- set canv .ctop.top.clist.canv
- canvas $canv -height $geometry(canvh) -width $geometry(canv1) \
+
+ # possibly use assumed geometry
+ if {![info exists geometry(pwsash0)]} {
+ set geometry(topheight) [expr {15 * $linespc}]
+ set geometry(topwidth) [expr {80 * $charspc}]
+ set geometry(botheight) [expr {15 * $linespc}]
+ set geometry(botwidth) [expr {50 * $charspc}]
+ set geometry(pwsash0) "[expr {40 * $charspc}] 2"
+ set geometry(pwsash1) "[expr {60 * $charspc}] 2"
+ }
+
+ # the upper half will have a paned window, a scroll bar to the right, and some stuff below
+ frame .tf -height $geometry(topheight) -width $geometry(topwidth)
+ frame .tf.histframe
+ panedwindow .tf.histframe.pwclist -orient horizontal -sashpad 0 -handlesize 4
+
+ # create three canvases
+ set cscroll .tf.histframe.csb
+ set canv .tf.histframe.pwclist.canv
+ canvas $canv \
-background $bgcolor -bd 0 \
-yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
- .ctop.top.clist add $canv
- set canv2 .ctop.top.clist.canv2
- canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \
+ .tf.histframe.pwclist add $canv
+ set canv2 .tf.histframe.pwclist.canv2
+ canvas $canv2 \
-background $bgcolor -bd 0 -yscrollincr $linespc
- .ctop.top.clist add $canv2
- set canv3 .ctop.top.clist.canv3
- canvas $canv3 -height $geometry(canvh) -width $geometry(canv3) \
+ .tf.histframe.pwclist add $canv2
+ set canv3 .tf.histframe.pwclist.canv3
+ canvas $canv3 \
-background $bgcolor -bd 0 -yscrollincr $linespc
- .ctop.top.clist add $canv3
- bind .ctop.top.clist <Configure> {resizeclistpanes %W %w}
+ .tf.histframe.pwclist add $canv3
+ eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
+ eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
+
+ # a scroll bar to rule them
+ scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
+ pack $cscroll -side right -fill y
+ bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
lappend bglist $canv $canv2 $canv3
+ pack .tf.histframe.pwclist -fill both -expand 1 -side left
+
+ # we have two button bars at bottom of top frame. Bar 1
+ frame .tf.bar
+ frame .tf.lbar -height 15
- set sha1entry .ctop.top.bar.sha1
+ set sha1entry .tf.bar.sha1
set entries $sha1entry
- set sha1but .ctop.top.bar.sha1label
+ set sha1but .tf.bar.sha1label
button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
-command gotocommit -width 8 -font $uifont
$sha1but conf -disabledforeground [$sha1but cget -foreground]
- pack .ctop.top.bar.sha1label -side left
+ pack .tf.bar.sha1label -side left
entry $sha1entry -width 40 -font $textfont -textvariable sha1string
trace add variable sha1string write sha1change
pack $sha1entry -side left -pady 2
0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
}
- button .ctop.top.bar.leftbut -image bm-left -command goback \
+ button .tf.bar.leftbut -image bm-left -command goback \
-state disabled -width 26
- pack .ctop.top.bar.leftbut -side left -fill y
- button .ctop.top.bar.rightbut -image bm-right -command goforw \
+ pack .tf.bar.leftbut -side left -fill y
+ button .tf.bar.rightbut -image bm-right -command goforw \
-state disabled -width 26
- pack .ctop.top.bar.rightbut -side left -fill y
+ pack .tf.bar.rightbut -side left -fill y
- button .ctop.top.bar.findbut -text "Find" -command dofind -font $uifont
- pack .ctop.top.bar.findbut -side left
+ button .tf.bar.findbut -text "Find" -command dofind -font $uifont
+ pack .tf.bar.findbut -side left
set findstring {}
- set fstring .ctop.top.bar.findstring
+ set fstring .tf.bar.findstring
lappend entries $fstring
entry $fstring -width 30 -font $textfont -textvariable findstring
trace add variable findstring write find_change
- pack $fstring -side left -expand 1 -fill x
+ pack $fstring -side left -expand 1 -fill x -in .tf.bar
set findtype Exact
- set findtypemenu [tk_optionMenu .ctop.top.bar.findtype \
- findtype Exact IgnCase Regexp]
+ set findtypemenu [tk_optionMenu .tf.bar.findtype \
+ findtype Exact IgnCase Regexp]
trace add variable findtype write find_change
- .ctop.top.bar.findtype configure -font $uifont
- .ctop.top.bar.findtype.menu configure -font $uifont
+ .tf.bar.findtype configure -font $uifont
+ .tf.bar.findtype.menu configure -font $uifont
set findloc "All fields"
- tk_optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \
+ tk_optionMenu .tf.bar.findloc findloc "All fields" Headline \
Comments Author Committer
trace add variable findloc write find_change
- .ctop.top.bar.findloc configure -font $uifont
- .ctop.top.bar.findloc.menu configure -font $uifont
- pack .ctop.top.bar.findloc -side right
- pack .ctop.top.bar.findtype -side right
-
- label .ctop.top.lbar.flabel -text "Highlight: Commits " \
- -font $uifont
- pack .ctop.top.lbar.flabel -side left -fill y
+ .tf.bar.findloc configure -font $uifont
+ .tf.bar.findloc.menu configure -font $uifont
+ pack .tf.bar.findloc -side right
+ pack .tf.bar.findtype -side right
+
+ # build up the bottom bar of upper window
+ label .tf.lbar.flabel -text "Highlight: Commits " \
+ -font $uifont
+ pack .tf.lbar.flabel -side left -fill y
set gdttype "touching paths:"
- set gm [tk_optionMenu .ctop.top.lbar.gdttype gdttype "touching paths:" \
- "adding/removing string:"]
+ set gm [tk_optionMenu .tf.lbar.gdttype gdttype "touching paths:" \
+ "adding/removing string:"]
trace add variable gdttype write hfiles_change
$gm conf -font $uifont
- .ctop.top.lbar.gdttype conf -font $uifont
- pack .ctop.top.lbar.gdttype -side left -fill y
- entry .ctop.top.lbar.fent -width 25 -font $textfont \
+ .tf.lbar.gdttype conf -font $uifont
+ pack .tf.lbar.gdttype -side left -fill y
+ entry .tf.lbar.fent -width 25 -font $textfont \
-textvariable highlight_files
trace add variable highlight_files write hfiles_change
- lappend entries .ctop.top.lbar.fent
- pack .ctop.top.lbar.fent -side left -fill x -expand 1
- label .ctop.top.lbar.vlabel -text " OR in view" -font $uifont
- pack .ctop.top.lbar.vlabel -side left -fill y
+ lappend entries .tf.lbar.fent
+ pack .tf.lbar.fent -side left -fill x -expand 1
+ label .tf.lbar.vlabel -text " OR in view" -font $uifont
+ pack .tf.lbar.vlabel -side left -fill y
global viewhlmenu selectedhlview
- set viewhlmenu [tk_optionMenu .ctop.top.lbar.vhl selectedhlview None]
- $viewhlmenu entryconf 0 -command delvhighlight
+ set viewhlmenu [tk_optionMenu .tf.lbar.vhl selectedhlview None]
+ $viewhlmenu entryconf None -command delvhighlight
$viewhlmenu conf -font $uifont
- .ctop.top.lbar.vhl conf -font $uifont
- pack .ctop.top.lbar.vhl -side left -fill y
- label .ctop.top.lbar.rlabel -text " OR " -font $uifont
- pack .ctop.top.lbar.rlabel -side left -fill y
+ .tf.lbar.vhl conf -font $uifont
+ pack .tf.lbar.vhl -side left -fill y
+ label .tf.lbar.rlabel -text " OR " -font $uifont
+ pack .tf.lbar.rlabel -side left -fill y
global highlight_related
- set m [tk_optionMenu .ctop.top.lbar.relm highlight_related None \
- "Descendent" "Not descendent" "Ancestor" "Not ancestor"]
+ set m [tk_optionMenu .tf.lbar.relm highlight_related None \
+ "Descendent" "Not descendent" "Ancestor" "Not ancestor"]
$m conf -font $uifont
- .ctop.top.lbar.relm conf -font $uifont
+ .tf.lbar.relm conf -font $uifont
trace add variable highlight_related write vrel_change
- pack .ctop.top.lbar.relm -side left -fill y
-
- panedwindow .ctop.cdet -orient horizontal
- .ctop add .ctop.cdet
- frame .ctop.cdet.left
- frame .ctop.cdet.left.bot
- pack .ctop.cdet.left.bot -side bottom -fill x
- button .ctop.cdet.left.bot.search -text "Search" -command dosearch \
+ pack .tf.lbar.relm -side left -fill y
+
+ # Finish putting the upper half of the viewer together
+ pack .tf.lbar -in .tf -side bottom -fill x
+ pack .tf.bar -in .tf -side bottom -fill x
+ pack .tf.histframe -fill both -side top -expand 1
+ .ctop add .tf
+ .ctop paneconfigure .tf -height $geometry(topheight)
+ .ctop paneconfigure .tf -width $geometry(topwidth)
+
+ # now build up the bottom
+ panedwindow .pwbottom -orient horizontal
+
+ # lower left, a text box over search bar, scroll bar to the right
+ # if we know window height, then that will set the lower text height, otherwise
+ # we set lower text height which will drive window height
+ if {[info exists geometry(main)]} {
+ frame .bleft -width $geometry(botwidth)
+ } else {
+ frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
+ }
+ frame .bleft.top
+
+ button .bleft.top.search -text "Search" -command dosearch \
-font $uifont
- pack .ctop.cdet.left.bot.search -side left -padx 5
- set sstring .ctop.cdet.left.bot.sstring
+ pack .bleft.top.search -side left -padx 5
+ set sstring .bleft.top.sstring
entry $sstring -width 20 -font $textfont -textvariable searchstring
lappend entries $sstring
trace add variable searchstring write incrsearch
pack $sstring -side left -expand 1 -fill x
- set ctext .ctop.cdet.left.ctext
+ set ctext .bleft.ctext
text $ctext -background $bgcolor -foreground $fgcolor \
-state disabled -font $textfont \
- -width $geometry(ctextw) -height $geometry(ctexth) \
-yscrollcommand scrolltext -wrap none
- scrollbar .ctop.cdet.left.sb -command "$ctext yview"
- pack .ctop.cdet.left.sb -side right -fill y
+ scrollbar .bleft.sb -command "$ctext yview"
+ pack .bleft.top -side top -fill x
+ pack .bleft.sb -side right -fill y
pack $ctext -side left -fill both -expand 1
- .ctop.cdet add .ctop.cdet.left
lappend bglist $ctext
lappend fglist $ctext
$ctext tag conf msep -font [concat $textfont bold]
$ctext tag conf found -back yellow
- frame .ctop.cdet.right
- frame .ctop.cdet.right.mode
- radiobutton .ctop.cdet.right.mode.patch -text "Patch" \
+ .pwbottom add .bleft
+ .pwbottom paneconfigure .bleft -width $geometry(botwidth)
+
+ # lower right
+ frame .bright
+ frame .bright.mode
+ radiobutton .bright.mode.patch -text "Patch" \
-command reselectline -variable cmitmode -value "patch"
- radiobutton .ctop.cdet.right.mode.tree -text "Tree" \
+ radiobutton .bright.mode.tree -text "Tree" \
-command reselectline -variable cmitmode -value "tree"
- grid .ctop.cdet.right.mode.patch .ctop.cdet.right.mode.tree -sticky ew
- pack .ctop.cdet.right.mode -side top -fill x
- set cflist .ctop.cdet.right.cfiles
+ grid .bright.mode.patch .bright.mode.tree -sticky ew
+ pack .bright.mode -side top -fill x
+ set cflist .bright.cfiles
set indent [font measure $mainfont "nn"]
- text $cflist -width $geometry(cflistw) \
+ text $cflist \
-background $bgcolor -foreground $fgcolor \
-font $mainfont \
-tabs [list $indent [expr {2 * $indent}]] \
- -yscrollcommand ".ctop.cdet.right.sb set" \
+ -yscrollcommand ".bright.sb set" \
-cursor [. cget -cursor] \
-spacing1 1 -spacing3 1
lappend bglist $cflist
lappend fglist $cflist
- scrollbar .ctop.cdet.right.sb -command "$cflist yview"
- pack .ctop.cdet.right.sb -side right -fill y
+ scrollbar .bright.sb -command "$cflist yview"
+ pack .bright.sb -side right -fill y
pack $cflist -side left -fill both -expand 1
$cflist tag configure highlight \
-background [$cflist cget -selectbackground]
$cflist tag configure bold -font [concat $mainfont bold]
- .ctop.cdet add .ctop.cdet.right
- bind .ctop.cdet <Configure> {resizecdetpanes %W %w}
- pack .ctop -side top -fill both -expand 1
+ .pwbottom add .bright
+ .ctop add .pwbottom
+ # restore window position if known
+ if {[info exists geometry(main)]} {
+ wm geometry . "$geometry(main)"
+ }
+
+ bind .pwbottom <Configure> {resizecdetpanes %W %w}
+ pack .ctop -fill both -expand 1
bindall <1> {selcanvline %W %x %y}
#bindall <B1-Motion> {selcanvline %W %x %y}
bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
bind . <Control-KP_Add> {incrfont 1}
bind . <Control-minus> {incrfont -1}
bind . <Control-KP_Subtract> {incrfont -1}
- bind . <Destroy> {savestuff %W}
+ wm protocol . WM_DELETE_WINDOW doquit
bind . <Button-1> "click %W"
bind $fstring <Key-Return> dofind
bind $sha1entry <Key-Return> gotocommit
$rowctxmenu add command -label "Create tag" -command mktag
$rowctxmenu add command -label "Write commit to file" -command writecommit
$rowctxmenu add command -label "Create new branch" -command mkbranch
+ $rowctxmenu add command -label "Cherry-pick this commit" \
+ -command cherrypick
set headctxmenu .headctxmenu
menu $headctxmenu -tearoff 0
puts $f [list set fgcolor $fgcolor]
puts $f [list set colors $colors]
puts $f [list set diffcolors $diffcolors]
- puts $f "set geometry(width) [winfo width .ctop]"
- puts $f "set geometry(height) [winfo height .ctop]"
- puts $f "set geometry(canv1) [expr {[winfo width $canv]-2}]"
- puts $f "set geometry(canv2) [expr {[winfo width $canv2]-2}]"
- puts $f "set geometry(canv3) [expr {[winfo width $canv3]-2}]"
- puts $f "set geometry(canvh) [expr {[winfo height $canv]-2}]"
- set wid [expr {([winfo width $ctext] - 8) \
- / [font measure $textfont "0"]}]
- puts $f "set geometry(ctextw) $wid"
- set wid [expr {([winfo width $cflist] - 11) \
- / [font measure [$cflist cget -font] "0"]}]
- puts $f "set geometry(cflistw) $wid"
+
+ puts $f "set geometry(main) [wm geometry .]"
+ 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]\""
+ puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
+ puts $f "set geometry(botwidth) [winfo width .bleft]"
+ puts $f "set geometry(botheight) [winfo height .bleft]"
+
puts -nonewline $f "set permviews {"
for {set v 0} {$v < $nextviewnum} {incr v} {
if {$viewperm($v)} {
set newviewname($nextviewnum) "View $nextviewnum"
set newviewperm($nextviewnum) 0
set newviewargs($nextviewnum) [shellarglist $revtreeargs]
- vieweditor $top $nextviewnum "Gitk view definition"
+ vieweditor $top $nextviewnum "Gitk view definition"
}
proc editview {} {
proc allviewmenus {n op args} {
global viewhlmenu
- doviewmenu .bar.view 7 [list showview $n] $op $args
+ doviewmenu .bar.view 5 [list showview $n] $op $args
doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
}
set viewperm($n) $newviewperm($n)
if {$newviewname($n) ne $viewname($n)} {
set viewname($n) $newviewname($n)
- doviewmenu .bar.view 7 [list showview $n] \
+ doviewmenu .bar.view 5 [list showview $n] \
entryconf [list -label $viewname($n)]
doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
entryconf [list -label $viewname($n) -value $viewname($n)]
set curview $n
set selectedview $n
- .bar.view entryconf 2 -state [expr {$n == 0? "disabled": "normal"}]
- .bar.view entryconf 3 -state [expr {$n == 0? "disabled": "normal"}]
+ .bar.view entryconf Edit* -state [expr {$n == 0? "disabled": "normal"}]
+ .bar.view entryconf Delete* -state [expr {$n == 0? "disabled": "normal"}]
if {![info exists viewdata($n)]} {
set pending_select $selid
show_status "Reading commits..."
}
if {[info exists commfd($n)]} {
- layoutmore
+ layoutmore {}
} else {
finishcommits
}
return [list $r0 $r1]
}
-proc layoutmore {} {
+proc layoutmore {tmax} {
global rowlaidout rowoptim commitidx numcommits optim_delay
global uparrowlen curview
- set row $rowlaidout
- set rowlaidout [layoutrows $row $commitidx($curview) 0]
- set orow [expr {$rowlaidout - $uparrowlen - 1}]
- if {$orow > $rowoptim} {
- optimize_rows $rowoptim 0 $orow
- set rowoptim $orow
- }
- set canshow [expr {$rowoptim - $optim_delay}]
- if {$canshow > $numcommits} {
- showstuff $canshow
+ while {1} {
+ if {$rowoptim - $optim_delay > $numcommits} {
+ showstuff [expr {$rowoptim - $optim_delay}]
+ } elseif {$rowlaidout - $uparrowlen - 1 > $rowoptim} {
+ set nr [expr {$rowlaidout - $uparrowlen - 1 - $rowoptim}]
+ if {$nr > 100} {
+ set nr 100
+ }
+ optimize_rows $rowoptim 0 [expr {$rowoptim + $nr}]
+ incr rowoptim $nr
+ } elseif {$commitidx($curview) > $rowlaidout} {
+ set nr [expr {$commitidx($curview) - $rowlaidout}]
+ # may need to increase this threshold if uparrowlen or
+ # mingaplen are increased...
+ if {$nr > 150} {
+ set nr 150
+ }
+ set row $rowlaidout
+ set rowlaidout [layoutrows $row [expr {$row + $nr}] 0]
+ if {$rowlaidout == $row} {
+ return 0
+ }
+ } else {
+ return 0
+ }
+ if {$tmax ne {} && [clock clicks -milliseconds] >= $tmax} {
+ return 1
+ }
}
}
catch {unset pending_select}
}
+# Insert a new commit as the child of the commit on row $row.
+# The new commit will be displayed on row $row and the commits
+# on that row and below will move down one row.
+proc insertrow {row newcmit} {
+ global displayorder parentlist childlist commitlisted
+ global commitrow curview rowidlist rowoffsets numcommits
+ global rowrangelist idrowranges rowlaidout rowoptim numcommits
+ global linesegends selectedline
+
+ if {$row >= $numcommits} {
+ puts "oops, inserting new row $row but only have $numcommits rows"
+ return
+ }
+ set p [lindex $displayorder $row]
+ set displayorder [linsert $displayorder $row $newcmit]
+ set parentlist [linsert $parentlist $row $p]
+ set kids [lindex $childlist $row]
+ lappend kids $newcmit
+ lset childlist $row $kids
+ set childlist [linsert $childlist $row {}]
+ set commitlisted [linsert $commitlisted $row 1]
+ set l [llength $displayorder]
+ for {set r $row} {$r < $l} {incr r} {
+ set id [lindex $displayorder $r]
+ set commitrow($curview,$id) $r
+ }
+
+ set idlist [lindex $rowidlist $row]
+ set offs [lindex $rowoffsets $row]
+ set newoffs {}
+ foreach x $idlist {
+ if {$x eq {} || ($x eq $p && [llength $kids] == 1)} {
+ lappend newoffs {}
+ } else {
+ lappend newoffs 0
+ }
+ }
+ if {[llength $kids] == 1} {
+ set col [lsearch -exact $idlist $p]
+ lset idlist $col $newcmit
+ } else {
+ set col [llength $idlist]
+ lappend idlist $newcmit
+ lappend offs {}
+ lset rowoffsets $row $offs
+ }
+ set rowidlist [linsert $rowidlist $row $idlist]
+ set rowoffsets [linsert $rowoffsets [expr {$row+1}] $newoffs]
+
+ set rowrangelist [linsert $rowrangelist $row {}]
+ set l [llength $rowrangelist]
+ for {set r 0} {$r < $l} {incr r} {
+ set ranges [lindex $rowrangelist $r]
+ if {$ranges ne {} && [lindex $ranges end] >= $row} {
+ set newranges {}
+ foreach x $ranges {
+ if {$x >= $row} {
+ lappend newranges [expr {$x + 1}]
+ } else {
+ lappend newranges $x
+ }
+ }
+ lset rowrangelist $r $newranges
+ }
+ }
+ if {[llength $kids] > 1} {
+ set rp1 [expr {$row + 1}]
+ set ranges [lindex $rowrangelist $rp1]
+ if {$ranges eq {}} {
+ set ranges [list $row $rp1]
+ } elseif {[lindex $ranges end-1] == $rp1} {
+ lset ranges end-1 $row
+ }
+ lset rowrangelist $rp1 $ranges
+ }
+ foreach id [array names idrowranges] {
+ set ranges $idrowranges($id)
+ if {$ranges ne {} && [lindex $ranges end] >= $row} {
+ set newranges {}
+ foreach x $ranges {
+ if {$x >= $row} {
+ lappend newranges [expr {$x + 1}]
+ } else {
+ lappend newranges $x
+ }
+ }
+ set idrowranges($id) $newranges
+ }
+ }
+
+ set linesegends [linsert $linesegends $row {}]
+
+ incr rowlaidout
+ incr rowoptim
+ incr numcommits
+
+ if {[info exists selectedline] && $selectedline >= $row} {
+ incr selectedline
+ }
+ redisplay
+}
+
# Don't change the text pane cursor if it is currently the hand cursor,
# showing that we are over a sha1 ID link.
proc settextcursor {c} {
# add a list of tag or branch names at position pos
# returns the number of names inserted
-proc appendrefs {pos l var} {
- global ctext commitrow linknum curview idtags $var
+proc appendrefs {pos tags var} {
+ global ctext commitrow linknum curview $var
if {[catch {$ctext index $pos}]} {
return 0
}
- set tags {}
- foreach id $l {
- foreach tag [set $var\($id\)] {
- lappend tags [concat $tag $id]
- }
- }
- set tags [lsort -index 1 $tags]
+ set tags [lsort $tags]
set sep {}
foreach tag $tags {
- set name [lindex $tag 0]
- set id [lindex $tag 1]
+ set id [set $var\($tag\)]
set lk link$linknum
incr linknum
$ctext insert $pos $sep
- $ctext insert $pos $name $lk
+ $ctext insert $pos $tag $lk
$ctext tag conf $lk -foreground blue
if {[info exists commitrow($curview,$id)]} {
$ctext tag bind $lk <1> \
return [llength $tags]
}
+proc taglist {ids} {
+ global idtags
+
+ set tags {}
+ foreach id $ids {
+ foreach tag $idtags($id) {
+ lappend tags $tag
+ }
+ }
+ return $tags
+}
+
# called when we have finished computing the nearby tags
proc dispneartags {} {
global selectedline currentid ctext anc_tags desc_tags showneartags
set id $currentid
$ctext conf -state normal
if {[info exists desc_heads($id)]} {
- if {[appendrefs branch $desc_heads($id) idheads] > 1} {
+ if {[appendrefs branch $desc_heads($id) headids] > 1} {
$ctext insert "branch -2c" "es"
}
}
if {[info exists anc_tags($id)]} {
- appendrefs follows $anc_tags($id) idtags
+ appendrefs follows [taglist $anc_tags($id)] tagids
}
if {[info exists desc_tags($id)]} {
- appendrefs precedes $desc_tags($id) idtags
+ appendrefs precedes [taglist $desc_tags($id)] tagids
}
$ctext conf -state disabled
}
}
$ctext insert end "\n"
}
-
+
set headers {}
set olds [lindex $parentlist $l]
if {[llength $olds] > 1} {
$ctext mark set branch "end -1c"
$ctext mark gravity branch left
if {[info exists desc_heads($id)]} {
- if {[appendrefs branch $desc_heads($id) idheads] > 1} {
+ if {[appendrefs branch $desc_heads($id) headids] > 1} {
# turn "Branch" into "Branches"
$ctext insert "branch -2c" "es"
}
$ctext mark set follows "end -1c"
$ctext mark gravity follows left
if {[info exists anc_tags($id)]} {
- appendrefs follows $anc_tags($id) idtags
+ appendrefs follows [taglist $anc_tags($id)] tagids
}
$ctext insert end "\nPrecedes: "
$ctext mark set precedes "end -1c"
$ctext mark gravity precedes left
if {[info exists desc_tags($id)]} {
- appendrefs precedes $desc_tags($id) idtags
+ appendrefs precedes [taglist $desc_tags($id)] tagids
}
$ctext insert end "\n"
}
set l [expr $numcommits - 1]
}
unmarkmatches
- selectline $l 1
+ selectline $l 1
}
proc unselectline {} {
}
incr historyindex
if {$historyindex > 1} {
- .ctop.top.bar.leftbut conf -state normal
+ .tf.bar.leftbut conf -state normal
} else {
- .ctop.top.bar.leftbut conf -state disabled
+ .tf.bar.leftbut conf -state disabled
}
- .ctop.top.bar.rightbut conf -state disabled
+ .tf.bar.rightbut conf -state disabled
}
proc godo {elt} {
if {$historyindex > 1} {
incr historyindex -1
godo [lindex $history [expr {$historyindex - 1}]]
- .ctop.top.bar.rightbut conf -state normal
+ .tf.bar.rightbut conf -state normal
}
if {$historyindex <= 1} {
- .ctop.top.bar.leftbut conf -state disabled
+ .tf.bar.leftbut conf -state disabled
}
}
set cmd [lindex $history $historyindex]
incr historyindex
godo $cmd
- .ctop.top.bar.leftbut conf -state normal
+ .tf.bar.leftbut conf -state normal
}
if {$historyindex >= [llength $history]} {
- .ctop.top.bar.rightbut conf -state disabled
+ .tf.bar.rightbut conf -state disabled
}
}
}
}
+proc prevfile {} {
+ global difffilestart ctext
+ set prev [lindex $difffilestart 0]
+ set here [$ctext index @0,0]
+ foreach loc $difffilestart {
+ if {[$ctext compare $loc >= $here]} {
+ $ctext yview $prev
+ return
+ }
+ set prev $loc
+ }
+ $ctext yview $prev
+}
+
proc nextfile {} {
global difffilestart ctext
set here [$ctext index @0,0]
foreach loc $difffilestart {
if {[$ctext compare $loc > $here]} {
$ctext yview $loc
+ return
}
}
}
proc scrolltext {f0 f1} {
global searchstring
- .ctop.cdet.left.sb set $f0 $f1
+ .bleft.sb set $f0 $f1
if {$searchstring ne {}} {
searchmarkvisible 0
}
drawvisible
if {[info exists selectedline]} {
selectline $selectedline 0
+ allcanvs yview moveto [lindex $span 0]
}
}
} else {
set state normal
}
- $rowctxmenu entryconfigure 0 -state $state
- $rowctxmenu entryconfigure 1 -state $state
- $rowctxmenu entryconfigure 2 -state $state
+ $rowctxmenu entryconfigure "Diff this*" -state $state
+ $rowctxmenu entryconfigure "Diff selected*" -state $state
+ $rowctxmenu entryconfigure "Make patch" -state $state
set rowmenuid $id
tk_popup $rowctxmenu $x $y
}
set tagids($tag) $id
lappend idtags($id) $tag
redrawtags $id
+ addedtag $id
}
proc redrawtags {id} {
notbusy newbranch
error_popup $err
} else {
- set headids($name) $id
- if {![info exists idheads($id)]} {
- addedhead $id
- }
- lappend idheads($id) $name
+ addedhead $id $name
# XXX should update list of heads displayed for selected commit
notbusy newbranch
redrawtags $id
}
}
+proc cherrypick {} {
+ global rowmenuid curview commitrow
+ global mainhead desc_heads anc_tags desc_tags allparents allchildren
+
+ if {[info exists desc_heads($rowmenuid)]
+ && [lsearch -exact $desc_heads($rowmenuid) $mainhead] >= 0} {
+ set ok [confirm_popup "Commit [string range $rowmenuid 0 7] is already\
+ included in branch $mainhead -- really re-apply it?"]
+ if {!$ok} return
+ }
+ nowbusy cherrypick
+ update
+ set oldhead [exec git rev-parse HEAD]
+ # Unfortunately git-cherry-pick writes stuff to stderr even when
+ # 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
+ return
+ }
+ set newhead [exec git rev-parse HEAD]
+ if {$newhead eq $oldhead} {
+ notbusy cherrypick
+ error_popup "No changes committed"
+ return
+ }
+ set allparents($newhead) $oldhead
+ lappend allchildren($oldhead) $newhead
+ set desc_heads($newhead) $mainhead
+ if {[info exists anc_tags($oldhead)]} {
+ set anc_tags($newhead) $anc_tags($oldhead)
+ }
+ set desc_tags($newhead) {}
+ if {[info exists commitrow($curview,$oldhead)]} {
+ insertrow $commitrow($curview,$oldhead) $newhead
+ if {$mainhead ne {}} {
+ movedhead $newhead $mainhead
+ }
+ redrawtags $oldhead
+ redrawtags $newhead
+ }
+ notbusy cherrypick
+}
+
# context menu for a head
proc headmenu {x y id head} {
global headmenuid headmenuhead headctxmenu
error_popup $err
} else {
notbusy checkout
- set maainhead $headmenuhead
+ set mainhead $headmenuhead
if {[info exists headids($oldmainhead)]} {
redrawtags $headids($oldmainhead)
}
error_popup "Cannot delete the currently checked-out branch"
return
}
- if {$desc_heads($id) eq $id} {
+ if {$desc_heads($id) eq $head} {
# the stuff on this branch isn't on any other branch
if {![confirm_popup "The commits on branch $head aren't on any other\
branch.\nReally delete branch $head?"]} return
error_popup $err
return
}
- unset headids($head)
- if {$idheads($id) eq $head} {
- unset idheads($id)
- removedhead $id
- } else {
- set i [lsearch -exact $idheads($id) $head]
- if {$i >= 0} {
- set idheads($id) [lreplace $idheads($id) $i $i]
- }
- }
+ removedhead $id $head
redrawtags $id
notbusy rmbranch
}
}
}
if {[info exists idheads($id)]} {
- lappend dheads $id
+ set dheads [concat $dheads $idheads($id)]
}
set desc_heads($id) $dheads
}
proc getallclines {fd} {
global allparents allchildren allcommits allcstart
global desc_tags anc_tags idtags tagisdesc allids
- global desc_heads idheads travindex
+ global idheads travindex
while {[gets $fd line] >= 0} {
set id [lindex $line 0]
dispneartags
}
+# update the desc_tags and anc_tags arrays for a new tag just added
+proc addedtag {id} {
+ global desc_tags anc_tags allparents allchildren allcommits
+ global idtags tagisdesc alldtags
+
+ if {![info exists desc_tags($id)]} return
+ set adt $desc_tags($id)
+ foreach t $desc_tags($id) {
+ set adt [concat $adt $alldtags($t)]
+ }
+ set adt [lsort -unique $adt]
+ set alldtags($id) $adt
+ foreach t $adt {
+ set tagisdesc($id,$t) -1
+ set tagisdesc($t,$id) 1
+ }
+ if {[info exists anc_tags($id)]} {
+ set todo $anc_tags($id)
+ while {$todo ne {}} {
+ set do [lindex $todo 0]
+ set todo [lrange $todo 1 end]
+ if {[info exists tagisdesc($id,$do)]} continue
+ set tagisdesc($do,$id) -1
+ set tagisdesc($id,$do) 1
+ if {[info exists anc_tags($do)]} {
+ set todo [concat $todo $anc_tags($do)]
+ }
+ }
+ }
+
+ set lastold $desc_tags($id)
+ set lastnew [list $id]
+ set nup 0
+ set nch 0
+ set todo $allparents($id)
+ while {$todo ne {}} {
+ set do [lindex $todo 0]
+ set todo [lrange $todo 1 end]
+ if {![info exists desc_tags($do)]} continue
+ if {$desc_tags($do) ne $lastold} {
+ set lastold $desc_tags($do)
+ set lastnew [combine_dtags $lastold [list $id]]
+ incr nch
+ }
+ if {$lastold eq $lastnew} continue
+ set desc_tags($do) $lastnew
+ incr nup
+ if {![info exists idtags($do)]} {
+ set todo [concat $todo $allparents($do)]
+ }
+ }
+
+ if {![info exists anc_tags($id)]} return
+ set lastold $anc_tags($id)
+ set lastnew [list $id]
+ set nup 0
+ set nch 0
+ set todo $allchildren($id)
+ while {$todo ne {}} {
+ set do [lindex $todo 0]
+ set todo [lrange $todo 1 end]
+ if {![info exists anc_tags($do)]} continue
+ if {$anc_tags($do) ne $lastold} {
+ set lastold $anc_tags($do)
+ set lastnew [combine_atags $lastold [list $id]]
+ incr nch
+ }
+ if {$lastold eq $lastnew} continue
+ set anc_tags($do) $lastnew
+ incr nup
+ if {![info exists idtags($do)]} {
+ set todo [concat $todo $allchildren($do)]
+ }
+ }
+}
+
# update the desc_heads array for a new head just added
-proc addedhead {hid} {
- global desc_heads allparents
+proc addedhead {hid head} {
+ global desc_heads allparents headids idheads
+
+ set headids($head) $hid
+ lappend idheads($hid) $head
set todo [list $hid]
while {$todo ne {}} {
set do [lindex $todo 0]
set todo [lrange $todo 1 end]
if {![info exists desc_heads($do)] ||
- [lsearch -exact $desc_heads($do) $hid] >= 0} continue
+ [lsearch -exact $desc_heads($do) $head] >= 0} continue
set oldheads $desc_heads($do)
- lappend desc_heads($do) $hid
+ lappend desc_heads($do) $head
set heads $desc_heads($do)
while {1} {
set p $allparents($do)
}
# update the desc_heads array for a head just removed
-proc removedhead {hid} {
- global desc_heads allparents
+proc removedhead {hid head} {
+ global desc_heads allparents headids idheads
+
+ unset headids($head)
+ if {$idheads($hid) eq $head} {
+ unset idheads($hid)
+ } else {
+ set i [lsearch -exact $idheads($hid) $head]
+ if {$i >= 0} {
+ set idheads($hid) [lreplace $idheads($hid) $i $i]
+ }
+ }
set todo [list $hid]
while {$todo ne {}} {
set do [lindex $todo 0]
set todo [lrange $todo 1 end]
if {![info exists desc_heads($do)]} continue
- set i [lsearch -exact $desc_heads($do) $hid]
+ set i [lsearch -exact $desc_heads($do) $head]
if {$i < 0} continue
set oldheads $desc_heads($do)
set heads [lreplace $desc_heads($do) $i $i]
}
}
+# update things for a head moved to a child of its previous location
+proc movedhead {id name} {
+ global headids idheads
+
+ set oldid $headids($name)
+ set headids($name) $id
+ if {$idheads($oldid) eq $name} {
+ unset idheads($oldid)
+ } else {
+ set i [lsearch -exact $idheads($oldid) $name]
+ if {$i >= 0} {
+ set idheads($oldid) [lreplace $idheads($oldid) $i $i]
+ }
+ }
+ lappend idheads($id) $name
+}
+
proc changedrefs {} {
global desc_heads desc_tags anc_tags allcommits allids
global allchildren allparents idtags travindex
proc doquit {} {
global stopped
set stopped 100
+ savestuff .
destroy .
}
set gitencoding {}
catch {
- set gitencoding [exec git repo-config --get i18n.commitencoding]
+ set gitencoding [exec git config --get i18n.commitencoding]
}
if {$gitencoding == ""} {
set gitencoding "utf-8"
set patchnum 0
setcoords
makewindow
+wm title . "[file tail $argv0]: [file tail [pwd]]"
readrefs
if {$cmdline_files ne {} || $revtreeargs ne {}} {
set viewargs(1) $revtreeargs
set viewperm(1) 0
addviewmenu 1
- .bar.view entryconf 2 -state normal
- .bar.view entryconf 3 -state normal
+ .bar.view entryconf Edit* -state normal
+ .bar.view entryconf Delete* -state normal
}
if {[info exists permviews]} {