proc start_rev_list {view} {
global startmsecs
global commfd leftover tclencoding datemode
- global viewargs viewfiles commitidx
+ global viewargs viewfiles commitidx vnextroot
global lookingforhead showlocalchanges
set startmsecs [clock clicks -milliseconds]
set commitidx($view) 0
- set args $viewargs($view)
- if {$viewfiles($view) ne {}} {
- set args [concat $args "--" $viewfiles($view)]
- }
+ set vnextroot($view) 0
set order "--topo-order"
if {$datemode} {
set order "--date-order"
}
if {[catch {
- set fd [open [concat | git rev-list --header $order \
- --parents --boundary --default HEAD $args] r]
+ set fd [open [concat | git log -z --pretty=raw $order --parents \
+ --boundary $viewargs($view) "--" $viewfiles($view)] r]
} err]} {
- puts stderr "Error executing git rev-list: $err"
+ error_popup "Error executing git rev-list: $err"
exit 1
}
set commfd($view) $fd
set leftover($view) {}
set lookingforhead $showlocalchanges
- fconfigure $fd -blocking 0 -translation lf
+ fconfigure $fd -blocking 0 -translation lf -eofchar {}
if {$tclencoding != {}} {
fconfigure $fd -encoding $tclencoding
}
show_status "Reading commits..."
}
+# This makes a string representation of a positive integer which
+# sorts as a string in numerical order
+proc strrep {n} {
+ if {$n < 16} {
+ return [format "%x" $n]
+ } elseif {$n < 256} {
+ return [format "x%.2x" $n]
+ } elseif {$n < 65536} {
+ return [format "y%.4x" $n]
+ }
+ return [format "z%.8x" $n]
+}
+
proc getcommitlines {fd view} {
global commitlisted
global leftover commfd
global displayorder commitidx commitrow commitdata
- global parentlist childlist children curview hlview
- global vparentlist vchildlist vdisporder vcmitlisted
+ global parentlist children curview hlview
+ global vparentlist vdisporder vcmitlisted
+ global ordertok vnextroot
set stuff [read $fd 500000]
+ # git log doesn't terminate the last commit with a null...
+ if {$stuff == {} && $leftover($view) ne {} && [eof $fd]} {
+ set stuff "\0"
+ }
if {$stuff == {}} {
if {![eof $fd]} {
return 1
set j [string first "\n" $cmit]
set ok 0
set listed 1
- if {$j >= 0} {
- set ids [string range $cmit 0 [expr {$j - 1}]]
- if {[string range $ids 0 0] == "-"} {
- set listed 0
+ if {$j >= 0 && [string match "commit *" $cmit]} {
+ set ids [string range $cmit 7 [expr {$j - 1}]]
+ if {[string match {[-<>]*} $ids]} {
+ switch -- [string index $ids 0] {
+ "-" {set listed 0}
+ "<" {set listed 2}
+ ">" {set listed 3}
+ }
set ids [string range $ids 1 end]
}
set ok 1
if {[string length $shortcmit] > 80} {
set shortcmit "[string range $shortcmit 0 80]..."
}
- error_popup "Can't parse git rev-list output: {$shortcmit}"
+ error_popup "Can't parse git log output: {$shortcmit}"
exit 1
}
set id [lindex $ids 0]
+ if {![info exists ordertok($view,$id)]} {
+ set otok "o[strrep $vnextroot($view)]"
+ incr vnextroot($view)
+ set ordertok($view,$id) $otok
+ } else {
+ set otok $ordertok($view,$id)
+ }
if {$listed} {
set olds [lrange $ids 1 end]
- set i 0
- foreach p $olds {
- if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
- lappend children($view,$p) $id
+ if {[llength $olds] == 1} {
+ set p [lindex $olds 0]
+ lappend children($view,$p) $id
+ if {![info exists ordertok($view,$p)]} {
+ set ordertok($view,$p) $ordertok($view,$id)
+ }
+ } else {
+ set i 0
+ foreach p $olds {
+ if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
+ lappend children($view,$p) $id
+ }
+ if {![info exists ordertok($view,$p)]} {
+ set ordertok($view,$p) "$otok[strrep $i]]"
+ }
+ incr i
}
- incr i
}
} else {
set olds {}
incr commitidx($view)
if {$view == $curview} {
lappend parentlist $olds
- lappend childlist $children($view,$id)
lappend displayorder $id
lappend commitlisted $listed
} else {
lappend vparentlist($view) $olds
- lappend vchildlist($view) $children($view,$id)
lappend vdisporder($view) $id
lappend vcmitlisted($view) $listed
}
set tlimit [expr {[clock clicks -milliseconds] + 50}]
set more [layoutmore $tlimit $allread]
if {$allread && !$more} {
- global displayorder nullid commitidx phase
+ global displayorder commitidx phase
global numcommits startmsecs
if {[info exists pending_select]} {
- set row [expr {[lindex $displayorder 0] eq $nullid}]
+ set row [first_real_row]
selectline $row 1
}
if {$commitidx($curview) > 0} {
}
}
+# skip over fake commits
+proc first_real_row {} {
+ global nullid nullid2 displayorder numcommits
+
+ for {set row 0} {$row < $numcommits} {incr row} {
+ set id [lindex $displayorder $row]
+ if {$id ne $nullid && $id ne $nullid2} {
+ break
+ }
+ }
+ return $row
+}
+
# update things for a head moved to a child of its previous location
proc movehead {id name} {
global headids idheads
wm geometry . "$geometry(main)"
}
+ if {[tk windowingsystem] eq {aqua}} {
+ set M1B M1
+ } else {
+ set M1B Control
+ }
+
bind .pwbottom <Configure> {resizecdetpanes %W %w}
pack .ctop -fill both -expand 1
bindall <1> {selcanvline %W %x %y}
bindkey <Key-Left> "goback"
bind . <Key-Prior> "selnextpage -1"
bind . <Key-Next> "selnextpage 1"
- bind . <Control-Home> "allcanvs yview moveto 0.0"
- bind . <Control-End> "allcanvs yview moveto 1.0"
- bind . <Control-Key-Up> "allcanvs yview scroll -1 units"
- bind . <Control-Key-Down> "allcanvs yview scroll 1 units"
- bind . <Control-Key-Prior> "allcanvs yview scroll -1 pages"
- bind . <Control-Key-Next> "allcanvs yview scroll 1 pages"
+ bind . <$M1B-Home> "allcanvs yview moveto 0.0"
+ bind . <$M1B-End> "allcanvs yview moveto 1.0"
+ bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
+ bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
+ bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
+ bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
bindkey <Key-Delete> "$ctext yview scroll -1 pages"
bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
bindkey <Key-space> "$ctext yview scroll 1 pages"
bindkey ? findprev
bindkey f nextfile
bindkey <F5> updatecommits
- bind . <Control-q> doquit
- bind . <Control-f> dofind
- bind . <Control-g> {findnext 0}
- bind . <Control-r> dosearchback
- bind . <Control-s> dosearch
- bind . <Control-equal> {incrfont 1}
- bind . <Control-KP_Add> {incrfont 1}
- bind . <Control-minus> {incrfont -1}
- bind . <Control-KP_Subtract> {incrfont -1}
+ bind . <$M1B-q> doquit
+ bind . <$M1B-f> dofind
+ bind . <$M1B-g> {findnext 0}
+ bind . <$M1B-r> dosearchback
+ bind . <$M1B-s> dosearch
+ bind . <$M1B-equal> {incrfont 1}
+ bind . <$M1B-KP_Add> {incrfont 1}
+ bind . <$M1B-minus> {incrfont -1}
+ bind . <$M1B-KP_Subtract> {incrfont -1}
wm protocol . WM_DELETE_WINDOW doquit
bind . <Button-1> "click %W"
bind $fstring <Key-Return> dofind
bind $cflist <1> {sel_flist %W %x %y; break}
bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
+ bind $cflist <Button-3> {pop_flist_menu %W %X %Y %x %y}
set maincursor [. cget -cursor]
set textcursor [$ctext cget -cursor]
$rowctxmenu add command -label "Create new branch" -command mkbranch
$rowctxmenu add command -label "Cherry-pick this commit" \
-command cherrypick
+ $rowctxmenu add command -label "Reset HEAD branch to here" \
+ -command resethead
set fakerowmenu .fakerowmenu
menu $fakerowmenu -tearoff 0
-command cobranch
$headctxmenu add command -label "Remove this branch" \
-command rmbranch
+
+ global flist_menu
+ set flist_menu .flistctxmenu
+ menu $flist_menu -tearoff 0
+ $flist_menu add command -label "Highlight this too" \
+ -command {flist_hl 0}
+ $flist_menu add command -label "Highlight this only" \
+ -command {flist_hl 1}
}
# mouse-2 makes all windows scan vertically, but only the one
raise $w
return
}
+ if {[tk windowingsystem] eq {aqua}} {
+ set M1T Cmd
+ } else {
+ set M1T Ctrl
+ }
toplevel $w
wm title $w "Gitk key bindings"
- message $w.m -text {
+ message $w.m -text "
Gitk key bindings:
-<Ctrl-Q> Quit
+<$M1T-Q> Quit
<Home> Move to first commit
<End> Move to last commit
<Up>, p, i Move up one commit
<Right>, x, l Go forward in history list
<PageUp> Move up one page in commit list
<PageDown> Move down one page in commit list
-<Ctrl-Home> Scroll to top of commit list
-<Ctrl-End> Scroll to bottom of commit list
-<Ctrl-Up> Scroll commit list up one line
-<Ctrl-Down> Scroll commit list down one line
-<Ctrl-PageUp> Scroll commit list up one page
-<Ctrl-PageDown> Scroll commit list down one page
+<$M1T-Home> Scroll to top of commit list
+<$M1T-End> Scroll to bottom of commit list
+<$M1T-Up> Scroll commit list up one line
+<$M1T-Down> Scroll commit list down one line
+<$M1T-PageUp> Scroll commit list up one page
+<$M1T-PageDown> Scroll commit list down one page
<Shift-Up> Move to previous highlighted line
<Shift-Down> Move to next highlighted line
<Delete>, b Scroll diff view up one page
<Space> Scroll diff view down one page
u Scroll diff view up 18 lines
d Scroll diff view down 18 lines
-<Ctrl-F> Find
-<Ctrl-G> Move to next find hit
+<$M1T-F> Find
+<$M1T-G> Move to next find hit
<Return> Move to next find hit
/ Move to next find hit, or redo find
? Move to previous find hit
f Scroll diff view to next file
-<Ctrl-S> Search for next hit in diff view
-<Ctrl-R> Search for previous hit in diff view
-<Ctrl-KP+> Increase font size
-<Ctrl-plus> Increase font size
-<Ctrl-KP-> Decrease font size
-<Ctrl-minus> Decrease font size
+<$M1T-S> Search for next hit in diff view
+<$M1T-R> Search for previous hit in diff view
+<$M1T-KP+> Increase font size
+<$M1T-plus> Increase font size
+<$M1T-KP-> Decrease font size
+<$M1T-minus> Decrease font size
<F5> Update
-} \
+" \
-justify left -bg white -border 2 -relief groove
pack $w.m -side top -fill both -padx 2 -pady 2
$w.m configure -font $uifont
set treeheight($prefix) $ht
incr ht [lindex $htstack end]
set htstack [lreplace $htstack end end]
+ set prefixend [lindex $prefendstack end]
+ set prefendstack [lreplace $prefendstack end end]
+ set prefix [string range $prefix 0 $prefixend]
}
$w conf -state disabled
}
}
}
+proc pop_flist_menu {w X Y x y} {
+ global ctext cflist cmitmode flist_menu flist_menu_file
+ global treediffs diffids
+
+ set l [lindex [split [$w index "@$x,$y"] "."] 0]
+ if {$l <= 1} return
+ if {$cmitmode eq "tree"} {
+ set e [linetoelt $l]
+ if {[string index $e end] eq "/"} return
+ } else {
+ set e [lindex $treediffs($diffids) [expr {$l-2}]]
+ }
+ set flist_menu_file $e
+ tk_popup $flist_menu $X $Y
+}
+
+proc flist_hl {only} {
+ global flist_menu_file highlight_files
+
+ set x [shellquote $flist_menu_file]
+ if {$only || $highlight_files eq {}} {
+ set highlight_files $x
+ } else {
+ append highlight_files " " $x
+ }
+}
+
# Functions for adding and removing shell-type quoting
proc shellquote {str} {
proc showview {n} {
global curview viewdata viewfiles
- global displayorder parentlist childlist rowidlist rowoffsets
+ global displayorder parentlist rowidlist
global colormap rowtextx commitrow nextcolor canvxmax
global numcommits rowrangelist commitlisted idrowranges rowchk
global selectedline currentid canv canvy0
- global matchinglines treediffs
+ global treediffs
global pending_select phase
global commitidx rowlaidout rowoptim
global commfd
global selectedview selectfirst
- global vparentlist vchildlist vdisporder vcmitlisted
+ global vparentlist vdisporder vcmitlisted
global hlview selectedhlview
if {$n == $curview} return
}
unselectline
normalline
- stopfindproc
if {$curview >= 0} {
set vparentlist($curview) $parentlist
- set vchildlist($curview) $childlist
set vdisporder($curview) $displayorder
set vcmitlisted($curview) $commitlisted
if {$phase ne {}} {
set viewdata($curview) \
- [list $phase $rowidlist $rowoffsets $rowrangelist \
+ [list $phase $rowidlist {} $rowrangelist \
[flatten idrowranges] [flatten idinlist] \
$rowlaidout $rowoptim $numcommits]
} elseif {![info exists viewdata($curview)]
|| [lindex $viewdata($curview) 0] ne {}} {
set viewdata($curview) \
- [list {} $rowidlist $rowoffsets $rowrangelist]
+ [list {} $rowidlist {} $rowrangelist]
}
}
- catch {unset matchinglines}
catch {unset treediffs}
clear_display
if {[info exists hlview] && $hlview == $n} {
set phase [lindex $v 0]
set displayorder $vdisporder($n)
set parentlist $vparentlist($n)
- set childlist $vchildlist($n)
set commitlisted $vcmitlisted($n)
set rowidlist [lindex $v 1]
- set rowoffsets [lindex $v 2]
set rowrangelist [lindex $v 3]
if {$phase eq {}} {
set numcommits [llength $displayorder]
} elseif {$selid ne {}} {
set pending_select $selid
} else {
- set row [expr {[lindex $displayorder 0] eq $nullid}]
+ set row [first_real_row]
if {$row < $numcommits} {
selectline $row 0
} else {
if {$n != $curview && ![info exists viewdata($n)]} {
set viewdata($n) [list getcommits {{}} {{}} {} {} {} 0 0 0 {}]
set vparentlist($n) {}
- set vchildlist($n) {}
set vdisporder($n) {}
set vcmitlisted($n) {}
start_rev_list $n
set boldnamerows {}
catch {unset nhighlights}
unbolden
+ unmarkmatches
if {$findtype ne "Regexp"} {
set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
$findstring]
drawvisible
}
+proc doesmatch {f} {
+ global findtype findstring findpattern
+
+ if {$findtype eq "Regexp"} {
+ return [regexp $findstring $f]
+ } elseif {$findtype eq "IgnCase"} {
+ return [string match -nocase $findpattern $f]
+ } else {
+ return [string match $findpattern $f]
+ }
+}
+
proc askfindhighlight {row id} {
global nhighlights commitinfo iddrawn mainfont
- global findstring findtype findloc findpattern
+ global findloc
+ global markingmatches
if {![info exists commitinfo($id)]} {
getcommit $id
set isbold 0
set fldtypes {Headline Author Date Committer CDate Comments}
foreach f $info ty $fldtypes {
- if {$findloc ne "All fields" && $findloc ne $ty} {
- continue
- }
- if {$findtype eq "Regexp"} {
- set doesmatch [regexp $findstring $f]
- } elseif {$findtype eq "IgnCase"} {
- set doesmatch [string match -nocase $findpattern $f]
- } else {
- set doesmatch [string match $findpattern $f]
- }
- if {$doesmatch} {
+ if {($findloc eq "All fields" || $findloc eq $ty) &&
+ [doesmatch $f]} {
if {$ty eq "Author"} {
set isbold 2
- } else {
- set isbold 1
+ break
}
+ set isbold 1
}
}
- if {[info exists iddrawn($id)]} {
- if {$isbold && ![ishighlighted $row]} {
- bolden $row [concat $mainfont bold]
+ if {$isbold && [info exists iddrawn($id)]} {
+ set f [concat $mainfont bold]
+ if {![ishighlighted $row]} {
+ bolden $row $f
+ if {$isbold > 1} {
+ bolden_name $row $f
+ }
}
- if {$isbold >= 2} {
- bolden_name $row [concat $mainfont bold]
+ if {$markingmatches} {
+ markrowmatches $row $id
}
}
set nhighlights($row) $isbold
}
+proc markrowmatches {row id} {
+ global canv canv2 linehtag linentag commitinfo findloc
+
+ set headline [lindex $commitinfo($id) 0]
+ set author [lindex $commitinfo($id) 1]
+ $canv delete match$row
+ $canv2 delete match$row
+ if {$findloc eq "All fields" || $findloc eq "Headline"} {
+ set m [findmatches $headline]
+ if {$m ne {}} {
+ markmatches $canv $row $headline $linehtag($row) $m \
+ [$canv itemcget $linehtag($row) -font] $row
+ }
+ }
+ if {$findloc eq "All fields" || $findloc eq "Author"} {
+ set m [findmatches $author]
+ if {$m ne {}} {
+ markmatches $canv2 $row $author $linentag($row) $m \
+ [$canv2 itemcget $linentag($row) -font] $row
+ }
+ }
+}
+
proc vrel_change {name ix op} {
global highlight_related
}
proc usedinrange {id l1 l2} {
- global children commitrow childlist curview
+ global children commitrow curview
if {[info exists commitrow($curview,$id)]} {
set r $commitrow($curview,$id)
if {$l1 <= $r && $r <= $l2} {
return [expr {$r - $l1 + 1}]
}
- set kids [lindex $childlist $r]
- } else {
- set kids $children($curview,$id)
}
+ set kids $children($curview,$id)
foreach c $kids {
set r $commitrow($curview,$c)
if {$l1 <= $r && $r <= $l2} {
return 0
}
-proc sanity {row {full 0}} {
- global rowidlist rowoffsets
+# Work out where id should go in idlist so that order-token
+# values increase from left to right
+proc idcol {idlist id {i 0}} {
+ global ordertok curview
- set col -1
- set ids [lindex $rowidlist $row]
- foreach id $ids {
- incr col
- if {$id eq {}} continue
- if {$col < [llength $ids] - 1 &&
- [lsearch -exact -start [expr {$col+1}] $ids $id] >= 0} {
- puts "oops: [shortids $id] repeated in row $row col $col: {[shortids [lindex $rowidlist $row]]}"
- }
- set o [lindex $rowoffsets $row $col]
- set y $row
- set x $col
- while {$o ne {}} {
- incr y -1
- incr x $o
- if {[lindex $rowidlist $y $x] != $id} {
- puts "oops: rowoffsets wrong at row [expr {$y+1}] col [expr {$x-$o}]"
- puts " id=[shortids $id] check started at row $row"
- for {set i $row} {$i >= $y} {incr i -1} {
- puts " row $i ids={[shortids [lindex $rowidlist $i]]} offs={[lindex $rowoffsets $i]}"
- }
- break
- }
- if {!$full} break
- set o [lindex $rowoffsets $y $x]
+ set t $ordertok($curview,$id)
+ if {$i >= [llength $idlist] ||
+ $t < $ordertok($curview,[lindex $idlist $i])} {
+ if {$i > [llength $idlist]} {
+ set i [llength $idlist]
+ }
+ while {[incr i -1] >= 0 &&
+ $t < $ordertok($curview,[lindex $idlist $i])} {}
+ incr i
+ } else {
+ if {$t > $ordertok($curview,[lindex $idlist $i])} {
+ while {[incr i] < [llength $idlist] &&
+ $t >= $ordertok($curview,[lindex $idlist $i])} {}
}
}
+ return $i
}
-proc makeuparrow {oid x y z} {
- global rowidlist rowoffsets uparrowlen idrowranges displayorder
+proc makeuparrow {oid y x} {
+ global rowidlist uparrowlen idrowranges displayorder
for {set i 1} {$i < $uparrowlen && $y > 1} {incr i} {
incr y -1
- incr x $z
- set off0 [lindex $rowoffsets $y]
- for {set x0 $x} {1} {incr x0} {
- if {$x0 >= [llength $off0]} {
- set x0 [llength [lindex $rowoffsets [expr {$y-1}]]]
- break
- }
- set z [lindex $off0 $x0]
- if {$z ne {}} {
- incr x0 $z
- break
- }
- }
- set z [expr {$x0 - $x}]
- lset rowidlist $y [linsert [lindex $rowidlist $y] $x $oid]
- lset rowoffsets $y [linsert [lindex $rowoffsets $y] $x $z]
+ set idl [lindex $rowidlist $y]
+ set x [idcol $idl $oid $x]
+ lset rowidlist $y [linsert $idl $x $oid]
}
- set tmp [lreplace [lindex $rowoffsets $y] $x $x {}]
- lset rowoffsets $y [incrange $tmp [expr {$x+1}] -1]
lappend idrowranges($oid) [lindex $displayorder $y]
}
proc initlayout {} {
- global rowidlist rowoffsets displayorder commitlisted
+ global rowidlist displayorder commitlisted
global rowlaidout rowoptim
global idinlist rowchk rowrangelist idrowranges
global numcommits canvxmax canv
global nextcolor
- global parentlist childlist children
+ global parentlist
global colormap rowtextx
global selectfirst
set displayorder {}
set commitlisted {}
set parentlist {}
- set childlist {}
set rowrangelist {}
set nextcolor 0
set rowidlist {{}}
- set rowoffsets {{}}
catch {unset idinlist}
catch {unset rowchk}
set rowlaidout 0
set nr [expr {$commitidx($curview) - $rowlaidout}]
# may need to increase this threshold if uparrowlen or
# mingaplen are increased...
- if {$nr > 150} {
- set nr 150
+ if {$nr > 200} {
+ set nr 200
}
set row $rowlaidout
set rowlaidout [layoutrows $row [expr {$row + $nr}] $allread]
proc showstuff {canshow last} {
global numcommits commitrow pending_select selectedline curview
- global lookingforhead mainheadid displayorder nullid selectfirst
+ global lookingforhead mainheadid displayorder selectfirst
+ global lastscrollset
if {$numcommits == 0} {
global phase
allcanvs delete all
}
set r0 $numcommits
+ set prev $numcommits
set numcommits $canshow
- setcanvscroll
+ set t [clock clicks -milliseconds]
+ if {$prev < 100 || $last || $t - $lastscrollset > 500} {
+ set lastscrollset $t
+ setcanvscroll
+ }
set rows [visiblerows]
set r1 [lindex $rows 1]
if {$r1 >= $canshow} {
if {[info exists selectedline] || [info exists pending_select]} {
set selectfirst 0
} else {
- set l [expr {[lindex $displayorder 0] eq $nullid}]
+ set l [first_real_row]
selectline $l 1
set selectfirst 0
}
}
proc dohidelocalchanges {} {
- global lookingforhead localrow lserial
+ global lookingforhead localfrow localirow lserial
set lookingforhead 0
- if {$localrow >= 0} {
- removerow $localrow
- set localrow -1
+ if {$localfrow >= 0} {
+ removerow $localfrow
+ set localfrow -1
+ if {$localirow > 0} {
+ incr localirow -1
+ }
+ }
+ if {$localirow >= 0} {
+ removerow $localirow
+ set localirow -1
}
incr lserial
}
-# spawn off a process to do git diff-index HEAD
+# spawn off a process to do git diff-index --cached HEAD
proc dodiffindex {} {
- global localrow lserial
+ global localirow localfrow lserial
incr lserial
- set localrow -1
- set fd [open "|git diff-index HEAD" r]
+ set localfrow -1
+ set localirow -1
+ set fd [open "|git diff-index --cached HEAD" r]
fconfigure $fd -blocking 0
filerun $fd [list readdiffindex $fd $lserial]
}
proc readdiffindex {fd serial} {
- global localrow commitrow mainheadid nullid curview
+ global localirow commitrow mainheadid nullid2 curview
global commitinfo commitdata lserial
+ set isdiff 1
if {[gets $fd line] < 0} {
- if {[eof $fd]} {
- close $fd
- return 0
+ if {![eof $fd]} {
+ return 1
}
- return 1
+ set isdiff 0
+ }
+ # we only need to see one line and we don't really care what it says...
+ close $fd
+
+ # now see if there are any local changes not checked in to the index
+ if {$serial == $lserial} {
+ set fd [open "|git diff-files" r]
+ fconfigure $fd -blocking 0
+ filerun $fd [list readdifffiles $fd $serial]
+ }
+
+ if {$isdiff && $serial == $lserial && $localirow == -1} {
+ # add the line for the changes in the index to the graph
+ set localirow $commitrow($curview,$mainheadid)
+ set hl "Local changes checked in to index but not committed"
+ set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
+ set commitdata($nullid2) "\n $hl\n"
+ insertrow $localirow $nullid2
+ }
+ return 0
+}
+
+proc readdifffiles {fd serial} {
+ global localirow localfrow commitrow mainheadid nullid curview
+ global commitinfo commitdata lserial
+
+ set isdiff 1
+ if {[gets $fd line] < 0} {
+ if {![eof $fd]} {
+ return 1
+ }
+ set isdiff 0
}
# we only need to see one line and we don't really care what it says...
close $fd
- if {$serial == $lserial && $localrow == -1} {
+ if {$isdiff && $serial == $lserial && $localfrow == -1} {
# add the line for the local diff to the graph
- set localrow $commitrow($curview,$mainheadid)
- set hl "Local uncommitted changes"
+ if {$localirow >= 0} {
+ set localfrow $localirow
+ incr localirow
+ } else {
+ set localfrow $commitrow($curview,$mainheadid)
+ }
+ set hl "Local uncommitted changes, not checked in to index"
set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
set commitdata($nullid) "\n $hl\n"
- insertrow $localrow $nullid
+ insertrow $localfrow $nullid
}
return 0
}
proc layoutrows {row endrow last} {
- global rowidlist rowoffsets displayorder
+ global rowidlist displayorder
global uparrowlen downarrowlen maxwidth mingaplen
- global childlist parentlist
+ global children parentlist
global idrowranges
global commitidx curview
global idinlist rowchk rowrangelist
set idlist [lindex $rowidlist $row]
- set offs [lindex $rowoffsets $row]
while {$row < $endrow} {
set id [lindex $displayorder $row]
set oldolds {}
set newolds {}
- foreach p [lindex $parentlist $row] {
+ set olds [lindex $parentlist $row]
+ foreach p $olds {
if {![info exists idinlist($p)]} {
lappend newolds $p
} elseif {!$idinlist($p)} {
}
set nev [expr {[llength $idlist] + [llength $newolds]
+ [llength $oldolds] - $maxwidth + 1}]
- if {$nev > 0} {
+ if {1 || $nev > 0} {
if {!$last &&
$row + $uparrowlen + $mingaplen >= $commitidx($curview)} break
for {set x [llength $idlist]} {[incr x -1] >= 0} {} {
[expr {$row + $uparrowlen + $mingaplen}]]
if {$r == 0} {
set idlist [lreplace $idlist $x $x]
- set offs [lreplace $offs $x $x]
- set offs [incrange $offs $x 1]
set idinlist($i) 0
set rm1 [expr {$row - 1}]
lappend idrowranges($i) [lindex $displayorder $rm1]
- if {[incr nev -1] <= 0} break
+ #if {[incr nev -1] <= 0} break
continue
}
set rowchk($id) [expr {$row + $r}]
}
}
lset rowidlist $row $idlist
- lset rowoffsets $row $offs
}
set col [lsearch -exact $idlist $id]
if {$col < 0} {
- set col [llength $idlist]
- lappend idlist $id
+ set col [idcol $idlist $id]
+ set idlist [linsert $idlist $col $id]
lset rowidlist $row $idlist
- set z {}
- if {[lindex $childlist $row] ne {}} {
- set z [expr {[llength [lindex $rowidlist [expr {$row-1}]]] - $col}]
+ if {$children($curview,$id) ne {}} {
unset idinlist($id)
- }
- lappend offs $z
- lset rowoffsets $row $offs
- if {$z ne {}} {
- makeuparrow $id $col $row $z
+ makeuparrow $id $row $col
}
} else {
unset idinlist($id)
}
lappend rowrangelist $ranges
incr row
- set offs [ntimes [llength $idlist] 0]
- set l [llength $newolds]
- set idlist [eval lreplace \$idlist $col $col $newolds]
- set o 0
- if {$l != 1} {
- set offs [lrange $offs 0 [expr {$col - 1}]]
- foreach x $newolds {
- lappend offs {}
- incr o -1
- }
- incr o
- set tmp [expr {[llength $idlist] - [llength $offs]}]
- if {$tmp > 0} {
- set offs [concat $offs [ntimes $tmp $o]]
- }
- } else {
- lset offs $col {}
- }
+ set idlist [lreplace $idlist $col $col]
+ set x $col
foreach i $newolds {
+ set x [idcol $idlist $i $x]
+ set idlist [linsert $idlist $x $i]
set idinlist($i) 1
set idrowranges($i) $id
}
- incr col $l
foreach oid $oldolds {
set idinlist($oid) 1
- set idlist [linsert $idlist $col $oid]
- set offs [linsert $offs $col $o]
- makeuparrow $oid $col $row $o
- incr col
+ set x [idcol $idlist $oid $x]
+ set idlist [linsert $idlist $x $oid]
+ makeuparrow $oid $row $x
}
lappend rowidlist $idlist
- lappend rowoffsets $offs
}
return $row
}
proc addextraid {id row} {
global displayorder commitrow commitinfo
global commitidx commitlisted
- global parentlist childlist children curview
+ global parentlist children curview
incr commitidx($curview)
lappend displayorder $id
if {![info exists children($curview,$id)]} {
set children($curview,$id) {}
}
- lappend childlist $children($curview,$id)
}
proc layouttail {} {
- global rowidlist rowoffsets idinlist commitidx curview
+ global rowidlist idinlist commitidx curview
global idrowranges rowrangelist
set row $commitidx($curview)
set id [lindex $idlist $col]
addextraid $id $row
unset idinlist($id)
- lappend idrowranges($id) $row
+ lappend idrowranges($id) $id
lappend rowrangelist $idrowranges($id)
unset idrowranges($id)
incr row
- set offs [ntimes $col 0]
set idlist [lreplace $idlist $col $col]
lappend rowidlist $idlist
- lappend rowoffsets $offs
}
foreach id [array names idinlist] {
unset idinlist($id)
addextraid $id $row
lset rowidlist $row [list $id]
- lset rowoffsets $row 0
- makeuparrow $id 0 $row 0
- lappend idrowranges($id) $row
+ makeuparrow $id $row 0
+ lappend idrowranges($id) $id
lappend rowrangelist $idrowranges($id)
unset idrowranges($id)
incr row
lappend rowidlist {}
- lappend rowoffsets {}
}
}
proc insert_pad {row col npad} {
- global rowidlist rowoffsets
+ global rowidlist
set pad [ntimes $npad {}]
lset rowidlist $row [eval linsert [list [lindex $rowidlist $row]] $col $pad]
- set tmp [eval linsert [list [lindex $rowoffsets $row]] $col $pad]
- lset rowoffsets $row [incrange $tmp [expr {$col + $npad}] [expr {-$npad}]]
}
proc optimize_rows {row col endrow} {
- global rowidlist rowoffsets displayorder
+ global rowidlist displayorder
+ if {$row < 1} {
+ set row 1
+ }
+ set idlist [lindex $rowidlist [expr {$row - 1}]]
+ if {$row >= 2} {
+ set previdlist [lindex $rowidlist [expr {$row - 2}]]
+ } else {
+ set previdlist {}
+ }
for {} {$row < $endrow} {incr row} {
+ set pprevidlist $previdlist
+ set previdlist $idlist
set idlist [lindex $rowidlist $row]
- set offs [lindex $rowoffsets $row]
set haspad 0
- for {} {$col < [llength $offs]} {incr col} {
- if {[lindex $idlist $col] eq {}} {
+ set y0 [expr {$row - 1}]
+ set ym [expr {$row - 2}]
+ set x0 -1
+ set xm -1
+ for {} {$col < [llength $idlist]} {incr col} {
+ set id [lindex $idlist $col]
+ if {[lindex $previdlist $col] eq $id} continue
+ if {$id eq {}} {
set haspad 1
continue
}
- set z [lindex $offs $col]
- if {$z eq {}} continue
+ set x0 [lsearch -exact $previdlist $id]
+ if {$x0 < 0} continue
+ set z [expr {$x0 - $col}]
set isarrow 0
- set x0 [expr {$col + $z}]
- set y0 [expr {$row - 1}]
- set z0 [lindex $rowoffsets $y0 $x0]
+ set z0 {}
+ if {$ym >= 0} {
+ set xm [lsearch -exact $pprevidlist $id]
+ if {$xm >= 0} {
+ set z0 [expr {$xm - $x0}]
+ }
+ }
if {$z0 eq {}} {
- set id [lindex $idlist $col]
set ranges [rowranges $id]
if {$ranges ne {} && $y0 > [lindex $ranges 0]} {
set isarrow 1
# Line currently goes left too much;
# insert pads in the previous row, then optimize it
set npad [expr {-1 - $z + $isarrow}]
- set offs [incrange $offs $col $npad]
insert_pad $y0 $x0 $npad
if {$y0 > 0} {
optimize_rows $y0 $x0 $row
}
- set z [lindex $offs $col]
- set x0 [expr {$col + $z}]
- set z0 [lindex $rowoffsets $y0 $x0]
+ set previdlist [lindex $rowidlist $y0]
+ set x0 [lsearch -exact $previdlist $id]
+ set z [expr {$x0 - $col}]
+ if {$z0 ne {}} {
+ set pprevidlist [lindex $rowidlist $ym]
+ set xm [lsearch -exact $pprevidlist $id]
+ set z0 [expr {$xm - $x0}]
+ }
} elseif {$z > 1 || ($z > 0 && $isarrow)} {
# Line currently goes right too much;
- # insert pads in this line and adjust the next's rowoffsets
+ # insert pads in this line
set npad [expr {$z - 1 + $isarrow}]
- set y1 [expr {$row + 1}]
- set offs2 [lindex $rowoffsets $y1]
- set x1 -1
- foreach z $offs2 {
- incr x1
- if {$z eq {} || $x1 + $z < $col} continue
- if {$x1 + $z > $col} {
- incr npad
- }
- lset rowoffsets $y1 [incrange $offs2 $x1 $npad]
- break
- }
set pad [ntimes $npad {}]
set idlist [eval linsert \$idlist $col $pad]
- set tmp [eval linsert \$offs $col $pad]
incr col $npad
- set offs [incrange $tmp $col [expr {-$npad}]]
- set z [lindex $offs $col]
+ set z [expr {$x0 - $col}]
set haspad 1
}
- if {$z0 eq {} && !$isarrow} {
+ if {$z0 eq {} && !$isarrow && $ym >= 0} {
# this line links to its first child on row $row-2
- set rm2 [expr {$row - 2}]
- set id [lindex $displayorder $rm2]
- set xc [lsearch -exact [lindex $rowidlist $rm2] $id]
+ set id [lindex $displayorder $ym]
+ set xc [lsearch -exact $pprevidlist $id]
if {$xc >= 0} {
set z0 [expr {$xc - $x0}]
}
# avoid lines jigging left then immediately right
if {$z0 ne {} && $z < 0 && $z0 > 0} {
insert_pad $y0 $x0 1
- set offs [incrange $offs $col 1]
- optimize_rows $y0 [expr {$x0 + 1}] $row
+ incr x0
+ optimize_rows $y0 $x0 $row
+ set previdlist [lindex $rowidlist $y0]
+ set pprevidlist [lindex $rowidlist $ym]
}
}
if {!$haspad} {
- set o {}
# Find the first column that doesn't have a line going right
for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
- set o [lindex $offs $col]
- if {$o eq {}} {
+ set id [lindex $idlist $col]
+ if {$id eq {}} break
+ set x0 [lsearch -exact $previdlist $id]
+ if {$x0 < 0} {
# check if this is the link to the first child
- set id [lindex $idlist $col]
set ranges [rowranges $id]
if {$ranges ne {} && $row == [lindex $ranges 0]} {
# it is, work out offset to child
- set y0 [expr {$row - 1}]
set id [lindex $displayorder $y0]
- set x0 [lsearch -exact [lindex $rowidlist $y0] $id]
- if {$x0 >= 0} {
- set o [expr {$x0 - $col}]
- }
+ set x0 [lsearch -exact $previdlist $id]
}
}
- if {$o eq {} || $o <= 0} break
+ if {$x0 <= $col} break
}
# Insert a pad at that column as long as it has a line and
- # isn't the last column, and adjust the next row' offsets
- if {$o ne {} && [incr col] < [llength $idlist]} {
- set y1 [expr {$row + 1}]
- set offs2 [lindex $rowoffsets $y1]
- set x1 -1
- foreach z $offs2 {
- incr x1
- if {$z eq {} || $x1 + $z < $col} continue
- lset rowoffsets $y1 [incrange $offs2 $x1 1]
- break
- }
+ # isn't the last column
+ if {$x0 >= 0 && [incr col] < [llength $idlist]} {
set idlist [linsert $idlist $col {}]
- set tmp [linsert $offs $col {}]
- incr col
- set offs [incrange $tmp $col -1]
}
}
lset rowidlist $row $idlist
- lset rowoffsets $row $offs
set col 0
}
}
proc drawparentlinks {id row} {
global rowidlist canv colormap curview parentlist
- global idpos
+ global idpos linespc
set rowids [lindex $rowidlist $row]
set col [lsearch -exact $rowids $id]
set x [xc $row $col]
set y [yc $row]
set y2 [yc $row2]
+ set d [expr {int(0.4 * $linespc)}]
+ set ymid [expr {$y + $d}]
set ids [lindex $rowidlist $row2]
# rmx = right-most X coord used
set rmx 0
if {$x2 > $rmx} {
set rmx $x2
}
- if {[lsearch -exact $rowids $p] < 0} {
+ set j [lsearch -exact $rowids $p]
+ if {$j < 0} {
# drawlineseg will do this one for us
continue
}
assigncolor $p
# should handle duplicated parents here...
set coords [list $x $y]
- if {$i < $col - 1} {
- lappend coords [xc $row [expr {$i + 1}]] $y
- } elseif {$i > $col + 1} {
- lappend coords [xc $row [expr {$i - 1}]] $y
+ if {$i != $col} {
+ # if attaching to a vertical segment, draw a smaller
+ # slant for visual distinctness
+ if {$i == $j} {
+ if {$i < $col} {
+ lappend coords [expr {$x2 + $d}] $y $x2 $ymid
+ } else {
+ lappend coords [expr {$x2 - $d}] $y $x2 $ymid
+ }
+ } elseif {$i < $col && $i < $j} {
+ # segment slants towards us already
+ lappend coords [xc $row $j] $y
+ } else {
+ if {$i < $col - 1} {
+ lappend coords [expr {$x2 + $linespc}] $y
+ } elseif {$i > $col + 1} {
+ lappend coords [expr {$x2 - $linespc}] $y
+ }
+ lappend coords $x2 $y2
+ }
+ } else {
+ lappend coords $x2 $y2
}
- lappend coords $x2 $y2
set t [$canv create line $coords -width [linewidth $p] \
-fill $colormap($p) -tags lines.$p]
$canv lower $t
}
proc drawcmittext {id row col} {
- global linespc canv canv2 canv3 canvy0 fgcolor
+ global linespc canv canv2 canv3 canvy0 fgcolor curview
global commitlisted commitinfo rowidlist parentlist
global rowtextx idpos idtags idheads idotherrefs
global linehtag linentag linedtag
- global mainfont canvxmax boldrows boldnamerows fgcolor nullid
+ global mainfont canvxmax boldrows boldnamerows fgcolor nullid nullid2
+ # listed is 0 for boundary, 1 for normal, 2 for left, 3 for right
+ set listed [lindex $commitlisted $row]
if {$id eq $nullid} {
set ofill red
+ } elseif {$id eq $nullid2} {
+ set ofill green
} else {
- set ofill [expr {[lindex $commitlisted $row]? "blue": "white"}]
+ set ofill [expr {$listed != 0? "blue": "white"}]
}
set x [xc $row $col]
set y [yc $row]
set orad [expr {$linespc / 3}]
- set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
- [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
- -fill $ofill -outline $fgcolor -width 1 -tags circle]
+ if {$listed <= 1} {
+ set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
+ [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
+ -fill $ofill -outline $fgcolor -width 1 -tags circle]
+ } elseif {$listed == 2} {
+ # triangle pointing left for left-side commits
+ set t [$canv create polygon \
+ [expr {$x - $orad}] $y \
+ [expr {$x + $orad - 1}] [expr {$y - $orad}] \
+ [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
+ -fill $ofill -outline $fgcolor -width 1 -tags circle]
+ } else {
+ # triangle pointing right for right-side commits
+ set t [$canv create polygon \
+ [expr {$x + $orad - 1}] $y \
+ [expr {$x - $orad}] [expr {$y - $orad}] \
+ [expr {$x - $orad}] [expr {$y + $orad - 1}] \
+ -fill $ofill -outline $fgcolor -width 1 -tags circle]
+ }
$canv raise $t
$canv bind $t <1> {selcanvline {} %x %y}
set rmx [llength [lindex $rowidlist $row]]
proc drawcmitrow {row} {
global displayorder rowidlist
- global iddrawn
+ global iddrawn markingmatches
global commitinfo parentlist numcommits
global filehighlight fhighlights findstring nhighlights
global hlview vhighlights
if {$highlight_related ne "None" && ![info exists rhighlights($row)]} {
askrelhighlight $row $id
}
- if {[info exists iddrawn($id)]} return
- set col [lsearch -exact [lindex $rowidlist $row] $id]
- if {$col < 0} {
- puts "oops, row $row id $id not in list"
- return
+ if {![info exists iddrawn($id)]} {
+ set col [lsearch -exact [lindex $rowidlist $row] $id]
+ if {$col < 0} {
+ puts "oops, row $row id $id not in list"
+ return
+ }
+ if {![info exists commitinfo($id)]} {
+ getcommit $id
+ }
+ assigncolor $id
+ drawcmittext $id $row $col
+ set iddrawn($id) 1
}
- if {![info exists commitinfo($id)]} {
- getcommit $id
+ if {$markingmatches} {
+ markrowmatches $row $id
}
- assigncolor $id
- drawcmittext $id $row $col
- set iddrawn($id) 1
}
proc drawcommits {row {endrow {}}} {
for {} {$r <= $er} {incr r} {
set id [lindex $displayorder $r]
set wasdrawn [info exists iddrawn($id)]
- if {!$wasdrawn} {
- drawcmitrow $r
- }
+ drawcmitrow $r
if {$r == $er} break
set nextid [lindex $displayorder [expr {$r + 1}]]
if {$wasdrawn && [info exists iddrawn($nextid)]} {
}
proc findcrossings {id} {
- global rowidlist parentlist numcommits rowoffsets displayorder
+ global rowidlist parentlist numcommits displayorder
set cross {}
set ccross {}
set e [expr {$numcommits - 1}]
}
if {$e <= $s} continue
- set x [lsearch -exact [lindex $rowidlist $e] $id]
- if {$x < 0} {
- puts "findcrossings: oops, no [shortids $id] in row $e"
- continue
- }
for {set row $e} {[incr row -1] >= $s} {} {
+ set x [lsearch -exact [lindex $rowidlist $row] $id]
+ if {$x < 0} break
set olds [lindex $parentlist $row]
set kid [lindex $displayorder $row]
set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
}
}
}
- set inc [lindex $rowoffsets $row $x]
- if {$inc eq {}} break
- incr x $inc
}
}
return [concat $ccross {{}} $cross]
# 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 children
- global commitrow curview rowidlist rowoffsets numcommits
+ global displayorder parentlist commitlisted children
+ global commitrow curview rowidlist numcommits
global rowrangelist rowlaidout rowoptim numcommits
global selectedline rowchk commitidx
set p [lindex $displayorder $row]
set displayorder [linsert $displayorder $row $newcmit]
set parentlist [linsert $parentlist $row $p]
- set kids [lindex $childlist $row]
+ set kids $children($curview,$p)
lappend kids $newcmit
- lset childlist $row $kids
- set childlist [linsert $childlist $row {}]
set children($curview,$p) $kids
+ set children($curview,$newcmit) {}
set commitlisted [linsert $commitlisted $row 1]
set l [llength $displayorder]
for {set r $row} {$r < $l} {incr r} {
incr commitidx($curview)
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 {}]
if {[llength $kids] > 1} {
# Remove a commit that was inserted with insertrow on row $row.
proc removerow {row} {
- global displayorder parentlist childlist commitlisted children
- global commitrow curview rowidlist rowoffsets numcommits
+ global displayorder parentlist commitlisted children
+ global commitrow curview rowidlist numcommits
global rowrangelist idrowranges rowlaidout rowoptim numcommits
global linesegends selectedline rowchk commitidx
set p [lindex $parentlist $row]
set displayorder [lreplace $displayorder $row $row]
set parentlist [lreplace $parentlist $row $row]
- set childlist [lreplace $childlist $row $row]
set commitlisted [lreplace $commitlisted $row $row]
- set kids [lindex $childlist $row]
+ set kids $children($curview,$p)
set i [lsearch -exact $kids $id]
if {$i >= 0} {
set kids [lreplace $kids $i $i]
- lset childlist $row $kids
set children($curview,$p) $kids
}
set l [llength $displayorder]
incr commitidx($curview) -1
set rowidlist [lreplace $rowidlist $row $row]
- set rowoffsets [lreplace $rowoffsets $rp1 $rp1]
- if {$kids ne {}} {
- set offs [lindex $rowoffsets $row]
- set offs [lreplace $offs end end]
- lset rowoffsets $row $offs
- }
set rowrangelist [lreplace $rowrangelist $row $row]
if {[llength $kids] > 0} {
}
proc findmatches {f} {
- global findtype foundstring foundstrlen
+ global findtype findstring
if {$findtype == "Regexp"} {
- set matches [regexp -indices -all -inline $foundstring $f]
+ set matches [regexp -indices -all -inline $findstring $f]
} else {
+ set fs $findstring
if {$findtype == "IgnCase"} {
- set str [string tolower $f]
- } else {
- set str $f
+ set f [string tolower $f]
+ set fs [string tolower $fs]
}
set matches {}
set i 0
- while {[set j [string first $foundstring $str $i]] >= 0} {
- lappend matches [list $j [expr {$j+$foundstrlen-1}]]
- set i [expr {$j + $foundstrlen}]
+ set l [string length $fs]
+ while {[set j [string first $fs $f $i]] >= 0} {
+ lappend matches [list $j [expr {$j+$l-1}]]
+ set i [expr {$j + $l}]
}
}
return $matches
}
-proc dofind {} {
- global findtype findloc findstring markedmatches commitinfo
- global numcommits displayorder linehtag linentag linedtag
- global mainfont canv canv2 canv3 selectedline
- global matchinglines foundstring foundstrlen matchstring
- global commitdata
+proc dofind {{rev 0}} {
+ global findstring findstartline findcurline selectedline numcommits
- stopfindproc
unmarkmatches
cancel_next_highlight
focus .
- set matchinglines {}
- if {$findtype == "IgnCase"} {
- set foundstring [string tolower $findstring]
+ if {$findstring eq {} || $numcommits == 0} return
+ if {![info exists selectedline]} {
+ set findstartline [lindex [visiblerows] $rev]
} else {
- set foundstring $findstring
+ set findstartline $selectedline
}
- set foundstrlen [string length $findstring]
- if {$foundstrlen == 0} return
- regsub -all {[*?\[\\]} $foundstring {\\&} matchstring
- set matchstring "*$matchstring*"
- if {![info exists selectedline]} {
- set oldsel -1
+ set findcurline $findstartline
+ nowbusy finding
+ if {!$rev} {
+ run findmore
} else {
- set oldsel $selectedline
+ if {$findcurline == 0} {
+ set findcurline $numcommits
+ }
+ incr findcurline -1
+ run findmorerev
}
- set didsel 0
- set fldtypes {Headline Author Date Committer CDate Comments}
- set l -1
- foreach id $displayorder {
- set d $commitdata($id)
- incr l
- if {$findtype == "Regexp"} {
- set doesmatch [regexp $foundstring $d]
- } elseif {$findtype == "IgnCase"} {
- set doesmatch [string match -nocase $matchstring $d]
+}
+
+proc findnext {restart} {
+ global findcurline
+ if {![info exists findcurline]} {
+ if {$restart} {
+ dofind
} else {
- set doesmatch [string match $matchstring $d]
+ bell
}
- if {!$doesmatch} continue
+ } else {
+ run findmore
+ nowbusy finding
+ }
+}
+
+proc findprev {} {
+ global findcurline
+ if {![info exists findcurline]} {
+ dofind 1
+ } else {
+ run findmorerev
+ nowbusy finding
+ }
+}
+
+proc findmore {} {
+ global commitdata commitinfo numcommits findstring findpattern findloc
+ global findstartline findcurline displayorder
+
+ set fldtypes {Headline Author Date Committer CDate Comments}
+ set l [expr {$findcurline + 1}]
+ if {$l >= $numcommits} {
+ set l 0
+ }
+ if {$l <= $findstartline} {
+ set lim [expr {$findstartline + 1}]
+ } else {
+ set lim $numcommits
+ }
+ if {$lim - $l > 500} {
+ set lim [expr {$l + 500}]
+ }
+ set last 0
+ for {} {$l < $lim} {incr l} {
+ set id [lindex $displayorder $l]
+ # shouldn't happen unless git log doesn't give all the commits...
+ if {![info exists commitdata($id)]} continue
+ if {![doesmatch $commitdata($id)]} continue
if {![info exists commitinfo($id)]} {
getcommit $id
}
set info $commitinfo($id)
- set doesmatch 0
foreach f $info ty $fldtypes {
- if {$findloc != "All fields" && $findloc != $ty} {
- continue
- }
- set matches [findmatches $f]
- if {$matches == {}} continue
- set doesmatch 1
- if {$ty == "Headline"} {
- drawcommits $l
- markmatches $canv $l $f $linehtag($l) $matches $mainfont
- } elseif {$ty == "Author"} {
- drawcommits $l
- markmatches $canv2 $l $f $linentag($l) $matches $mainfont
- } elseif {$ty == "Date"} {
- drawcommits $l
- markmatches $canv3 $l $f $linedtag($l) $matches $mainfont
+ if {($findloc eq "All fields" || $findloc eq $ty) &&
+ [doesmatch $f]} {
+ findselectline $l
+ notbusy finding
+ return 0
}
}
- if {$doesmatch} {
- lappend matchinglines $l
- if {!$didsel && $l > $oldsel} {
+ }
+ if {$l == $findstartline + 1} {
+ bell
+ unset findcurline
+ notbusy finding
+ return 0
+ }
+ set findcurline [expr {$l - 1}]
+ return 1
+}
+
+proc findmorerev {} {
+ global commitdata commitinfo numcommits findstring findpattern findloc
+ global findstartline findcurline displayorder
+
+ set fldtypes {Headline Author Date Committer CDate Comments}
+ set l $findcurline
+ if {$l == 0} {
+ set l $numcommits
+ }
+ incr l -1
+ if {$l >= $findstartline} {
+ set lim [expr {$findstartline - 1}]
+ } else {
+ set lim -1
+ }
+ if {$l - $lim > 500} {
+ set lim [expr {$l - 500}]
+ }
+ set last 0
+ for {} {$l > $lim} {incr l -1} {
+ set id [lindex $displayorder $l]
+ if {![doesmatch $commitdata($id)]} continue
+ if {![info exists commitinfo($id)]} {
+ getcommit $id
+ }
+ set info $commitinfo($id)
+ foreach f $info ty $fldtypes {
+ if {($findloc eq "All fields" || $findloc eq $ty) &&
+ [doesmatch $f]} {
findselectline $l
- set didsel 1
+ notbusy finding
+ return 0
}
}
}
- if {$matchinglines == {}} {
+ if {$l == -1} {
bell
- } elseif {!$didsel} {
- findselectline [lindex $matchinglines 0]
+ unset findcurline
+ notbusy finding
+ return 0
}
+ set findcurline [expr {$l + 1}]
+ return 1
}
proc findselectline {l} {
- global findloc commentend ctext
+ global findloc commentend ctext findcurline markingmatches
+
+ set markingmatches 1
+ set findcurline $l
selectline $l 1
if {$findloc == "All fields" || $findloc == "Comments"} {
# highlight the matches in the comments
$ctext tag add found "1.0 + $start c" "1.0 + $end c"
}
}
+ drawvisible
}
-proc findnext {restart} {
- global matchinglines selectedline
- if {![info exists matchinglines]} {
- if {$restart} {
- dofind
- }
- return
- }
- if {![info exists selectedline]} return
- foreach l $matchinglines {
- if {$l > $selectedline} {
- findselectline $l
- return
- }
- }
- bell
-}
-
-proc findprev {} {
- global matchinglines selectedline
- if {![info exists matchinglines]} {
- dofind
- return
- }
- if {![info exists selectedline]} return
- set prev {}
- foreach l $matchinglines {
- if {$l >= $selectedline} break
- set prev $l
- }
- if {$prev != {}} {
- findselectline $prev
- } else {
- bell
- }
-}
-
-proc stopfindproc {{done 0}} {
- global findprocpid findprocfile findids
- global ctext findoldcursor phase maincursor textcursor
- global findinprogress
-
- catch {unset findids}
- if {[info exists findprocpid]} {
- if {!$done} {
- catch {exec kill $findprocpid}
- }
- catch {close $findprocfile}
- unset findprocpid
- }
- catch {unset findinprogress}
- notbusy find
-}
-
-# mark a commit as matching by putting a yellow background
-# behind the headline
-proc markheadline {l id} {
- global canv mainfont linehtag
-
- drawcommits $l
- set bbox [$canv bbox $linehtag($l)]
- set t [$canv create rect $bbox -outline {} -tags matches -fill yellow]
- $canv lower $t
-}
+# mark the bits of a headline or author that match a find string
+proc markmatches {canv l str tag matches font row} {
+ global selectedline
-# mark the bits of a headline, author or date that match a find string
-proc markmatches {canv l str tag matches font} {
set bbox [$canv bbox $tag]
set x0 [lindex $bbox 0]
set y0 [lindex $bbox 1]
set xlen [font measure $font [string range $str 0 [expr {$end}]]]
set t [$canv create rect [expr {$x0+$xoff}] $y0 \
[expr {$x0+$xlen+2}] $y1 \
- -outline {} -tags matches -fill yellow]
+ -outline {} -tags [list match$l matches] -fill yellow]
$canv lower $t
+ if {[info exists selectedline] && $row == $selectedline} {
+ $canv raise $t secsel
+ }
}
}
proc unmarkmatches {} {
- global matchinglines findids
+ global findids markingmatches findcurline
+
allcanvs delete matches
- catch {unset matchinglines}
catch {unset findids}
+ set markingmatches 0
+ catch {unset findcurline}
}
proc selcanvline {w x y} {
proc selectline {l isnew} {
global canv canv2 canv3 ctext commitinfo selectedline
global displayorder linehtag linentag linedtag
- global canvy0 linespc parentlist childlist
+ global canvy0 linespc parentlist children curview
global currentid sha1entry
global commentend idtags linknum
global mergemax numcommits pending_select
}
}
- foreach c [lindex $childlist $l] {
+ foreach c $children($curview,$id) {
append headers "Child: [commit_descriptor $c]"
}
}
appendwithlinks $comment {comment}
- $ctext tag delete Comments
$ctext tag remove found 1.0 end
$ctext conf -state disabled
set commentend [$ctext index "end - 1c"]
}
proc gettree {id} {
- global treefilelist treeidlist diffids diffmergeid treepending nullid
+ global treefilelist treeidlist diffids diffmergeid treepending
+ global nullid nullid2
set diffids $id
catch {unset diffmergeid}
if {![info exists treefilelist($id)]} {
if {![info exists treepending]} {
- if {$id ne $nullid} {
- set cmd [concat | git ls-tree -r $id]
+ if {$id eq $nullid} {
+ set cmd [list | git ls-files]
+ } elseif {$id eq $nullid2} {
+ set cmd [list | git ls-files --stage -t]
} else {
- set cmd [concat | git ls-files]
+ set cmd [list | git ls-tree -r $id]
}
if {[catch {set gtf [open $cmd r]}]} {
return
}
proc gettreeline {gtf id} {
- global treefilelist treeidlist treepending cmitmode diffids nullid
+ global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
set nl 0
while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
- if {$diffids ne $nullid} {
- set tl [split $line "\t"]
- if {[lindex $tl 0 1] ne "blob"} continue
- set sha1 [lindex $tl 0 2]
- set fname [lindex $tl 1]
+ if {$diffids eq $nullid} {
+ set fname $line
+ } else {
+ if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
+ set i [string first "\t" $line]
+ if {$i < 0} continue
+ set sha1 [lindex $line 2]
+ set fname [string range $line [expr {$i+1}] end]
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
lappend treeidlist($id) $sha1
- } else {
- set fname $line
}
lappend treefilelist($id) $fname
}
}
proc showfile {f} {
- global treefilelist treeidlist diffids nullid
+ global treefilelist treeidlist diffids nullid nullid2
global ctext commentend
set i [lsearch -exact $treefilelist($diffids) $f]
puts "oops, $f not in list for id $diffids"
return
}
- if {$diffids ne $nullid} {
- set blob [lindex $treeidlist($diffids) $i]
- if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
- puts "oops, error reading blob $blob: $err"
+ if {$diffids eq $nullid} {
+ if {[catch {set bf [open $f r]} err]} {
+ puts "oops, can't read $f: $err"
return
}
} else {
- if {[catch {set bf [open $f r]} err]} {
- puts "oops, can't read $f: $err"
+ set blob [lindex $treeidlist($diffids) $i]
+ if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
+ puts "oops, error reading blob $blob: $err"
return
}
}
}
proc startdiff {ids} {
- global treediffs diffids treepending diffmergeid nullid
+ global treediffs diffids treepending diffmergeid nullid nullid2
set diffids $ids
catch {unset diffmergeid}
- if {![info exists treediffs($ids)] || [lsearch -exact $ids $nullid] >= 0} {
+ if {![info exists treediffs($ids)] ||
+ [lsearch -exact $ids $nullid] >= 0 ||
+ [lsearch -exact $ids $nullid2] >= 0} {
if {![info exists treepending]} {
gettreediffs $ids
}
}
proc diffcmd {ids flags} {
- global nullid
+ global nullid nullid2
set i [lsearch -exact $ids $nullid]
+ set j [lsearch -exact $ids $nullid2]
if {$i >= 0} {
- set cmd [concat | git diff-index $flags]
+ if {[llength $ids] > 1 && $j < 0} {
+ # comparing working directory with some specific revision
+ set cmd [concat | git diff-index $flags]
+ if {$i == 0} {
+ lappend cmd -R [lindex $ids 1]
+ } else {
+ lappend cmd [lindex $ids 0]
+ }
+ } else {
+ # comparing working directory with index
+ set cmd [concat | git diff-files $flags]
+ if {$j == 1} {
+ lappend cmd -R
+ }
+ }
+ } elseif {$j >= 0} {
+ set cmd [concat | git diff-index --cached $flags]
if {[llength $ids] > 1} {
+ # comparing index with specific revision
if {$i == 0} {
lappend cmd -R [lindex $ids 1]
} else {
lappend cmd [lindex $ids 0]
}
} else {
+ # comparing index with HEAD
lappend cmd HEAD
}
} else {
- set cmd [concat | git diff-tree --no-commit-id -r $flags $ids]
+ set cmd [concat | git diff-tree -r $flags $ids]
}
return $cmd
}
set treepending $ids
set treediff {}
- if {[catch {set gdtf [open [diffcmd $ids {}] r]}]} return
+ if {[catch {set gdtf [open [diffcmd $ids {--no-commit-id}] r]}]} return
fconfigure $gdtf -blocking 0
filerun $gdtf [list gettreediffline $gdtf $ids]
}
set nr 0
while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
- set file [lindex $line 5]
- lappend treediff $file
+ set i [string first "\t" $line]
+ if {$i >= 0} {
+ set file [string range $line [expr {$i+1}] end]
+ if {[string index $file 0] eq "\""} {
+ set file [lindex $file 0]
+ }
+ lappend treediff $file
+ }
}
if {![eof $gdtf]} {
return [expr {$nr >= 1000? 2: 1}]
}
proc getblobdiffs {ids} {
- global diffopts blobdifffd diffids env curdifftag curtagstart
+ global diffopts blobdifffd diffids env
global diffinhdr treediffs
set env(GIT_DIFF_OPTS) $diffopts
- if {[catch {set bdf [open [diffcmd $ids {-p -C}] r]} err]} {
+ if {[catch {set bdf [open [diffcmd $ids {-p -C --no-commit-id}] r]} err]} {
puts "error getting diffs: $err"
return
}
set diffinhdr 0
fconfigure $bdf -blocking 0
set blobdifffd($ids) $bdf
- set curdifftag Comments
- set curtagstart 0.0
filerun $bdf [list getblobdiffline $bdf $diffids]
}
}
}
+proc makediffhdr {fname ids} {
+ global ctext curdiffstart treediffs
+
+ set i [lsearch -exact $treediffs($ids) $fname]
+ if {$i >= 0} {
+ setinlist difffilestart $i $curdiffstart
+ }
+ set l [expr {(78 - [string length $fname]) / 2}]
+ set pad [string range "----------------------------------------" 1 $l]
+ $ctext insert $curdiffstart "$pad $fname $pad" filesep
+}
+
proc getblobdiffline {bdf ids} {
- global diffids blobdifffd ctext curdifftag curtagstart
+ global diffids blobdifffd ctext curdiffstart
global diffnexthead diffnextnote difffilestart
global diffinhdr treediffs
close $bdf
return 0
}
- if {[regexp {^diff --git a/(.*) b/(.*)} $line match fname newname]} {
+ if {![string compare -length 11 "diff --git " $line]} {
+ # trim off "diff --git "
+ set line [string range $line 11 end]
+ set diffinhdr 1
# start of a new file
$ctext insert end "\n"
- $ctext tag add $curdifftag $curtagstart end
- set here [$ctext index "end - 1c"]
- set curtagstart $here
- set header $newname
- set i [lsearch -exact $treediffs($ids) $fname]
- if {$i >= 0} {
- setinlist difffilestart $i $here
+ set curdiffstart [$ctext index "end - 1c"]
+ $ctext insert end "\n" filesep
+ # If the name hasn't changed the length will be odd,
+ # the middle char will be a space, and the two bits either
+ # side will be a/name and b/name, or "a/name" and "b/name".
+ # If the name has changed we'll get "rename from" and
+ # "rename to" lines following this, and we'll use them
+ # to get the filenames.
+ # This complexity is necessary because spaces in the filename(s)
+ # don't get escaped.
+ set l [string length $line]
+ set i [expr {$l / 2}]
+ if {!(($l & 1) && [string index $line $i] eq " " &&
+ [string range $line 2 [expr {$i - 1}]] eq \
+ [string range $line [expr {$i + 3}] end])} {
+ continue
}
- if {$newname ne $fname} {
- set i [lsearch -exact $treediffs($ids) $newname]
- if {$i >= 0} {
- setinlist difffilestart $i $here
- }
+ # unescape if quoted and chop off the a/ from the front
+ if {[string index $line 0] eq "\""} {
+ set fname [string range [lindex $line 0] 2 end]
+ } else {
+ set fname [string range $line 2 [expr {$i - 1}]]
}
- set curdifftag "f:$fname"
- $ctext tag delete $curdifftag
- set l [expr {(78 - [string length $header]) / 2}]
- set pad [string range "----------------------------------------" \
- 1 $l]
- $ctext insert end "$pad $header $pad\n" filesep
- set diffinhdr 1
- } elseif {$diffinhdr && [string compare -length 3 $line "---"] == 0} {
- # do nothing
- } elseif {$diffinhdr && [string compare -length 3 $line "+++"] == 0} {
- set diffinhdr 0
- } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
+ makediffhdr $fname $ids
+
+ } elseif {[regexp {^@@ -([0-9]+)(,[0-9]+)? \+([0-9]+)(,[0-9]+)? @@(.*)} \
$line match f1l f1c f2l f2c rest]} {
$ctext insert end "$line\n" hunksep
set diffinhdr 0
+
+ } elseif {$diffinhdr} {
+ if {![string compare -length 12 "rename from " $line]} {
+ set fname [string range $line 12 end]
+ if {[string index $fname 0] eq "\""} {
+ set fname [lindex $fname 0]
+ }
+ set i [lsearch -exact $treediffs($ids) $fname]
+ if {$i >= 0} {
+ setinlist difffilestart $i $curdiffstart
+ }
+ } elseif {![string compare -length 10 $line "rename to "]} {
+ set fname [string range $line 10 end]
+ if {[string index $fname 0] eq "\""} {
+ set fname [lindex $fname 0]
+ }
+ makediffhdr $fname $ids
+ } elseif {[string compare -length 3 $line "---"] == 0} {
+ # do nothing
+ continue
+ } elseif {[string compare -length 3 $line "+++"] == 0} {
+ set diffinhdr 0
+ continue
+ }
+ $ctext insert end "$line\n" filesep
+
} else {
set x [string range $line 0 0]
if {$x == "-" || $x == "+"} {
$ctext insert end "$line\n" d$tag
} elseif {$x == " "} {
$ctext insert end "$line\n"
- } elseif {$diffinhdr || $x == "\\"} {
- # e.g. "\ No newline at end of file"
- $ctext insert end "$line\n" filesep
} else {
- # Something else we don't recognize
- if {$curdifftag != "Comments"} {
- $ctext insert end "\n"
- $ctext tag add $curdifftag $curtagstart end
- set curtagstart [$ctext index "end - 1c"]
- set curdifftag Comments
- }
- $ctext insert end "$line\n" filesep
+ # "\ No newline at end of file",
+ # or something else we don't recognize
+ $ctext insert end "$line\n" hunksep
}
}
}
$ctext conf -state disabled
if {[eof $bdf]} {
close $bdf
- if {$ids == $diffids && $bdf == $blobdifffd($ids)} {
- $ctext tag add $curdifftag $curtagstart end
- }
return 0
}
return [expr {$nr >= 1000? 2: 1}]
}
proc rowmenu {x y id} {
- global rowctxmenu commitrow selectedline rowmenuid curview nullid
- global fakerowmenu
+ global rowctxmenu commitrow selectedline rowmenuid curview
+ global nullid nullid2 fakerowmenu mainhead
set rowmenuid $id
if {![info exists selectedline]
} else {
set state normal
}
- if {$id ne $nullid} {
+ if {$id ne $nullid && $id ne $nullid2} {
set menu $rowctxmenu
+ $menu entryconfigure 7 -label "Reset $mainhead branch to here"
} else {
set menu $fakerowmenu
}
$ctext insert end [lindex $commitinfo($newid) 0]
$ctext insert end "\n"
$ctext conf -state disabled
- $ctext tag delete Comments
$ctext tag remove found 1.0 end
startdiff [list $oldid $newid]
}
}
proc mkpatchgo {} {
- global patchtop nullid
+ global patchtop nullid nullid2
set oldid [$patchtop.fromsha1 get]
set newid [$patchtop.tosha1 get]
set fname [$patchtop.fname get]
- if {$newid eq $nullid} {
- set cmd [list git diff-index -p $oldid]
- } elseif {$oldid eq $nullid} {
- set cmd [list git diff-index -p -R $newid]
- } else {
- set cmd [list git diff-tree -p $oldid $newid]
- }
+ set cmd [diffcmd [list $oldid $newid] -p]
lappend cmd >$fname &
if {[catch {eval exec $cmd} err]} {
error_popup "Error creating patch: $err"
notbusy cherrypick
}
+proc resethead {} {
+ global mainheadid mainhead rowmenuid confirm_ok resettype
+ global showlocalchanges
+
+ set confirm_ok 0
+ set w ".confirmreset"
+ toplevel $w
+ wm transient $w .
+ wm title $w "Confirm reset"
+ message $w.m -text \
+ "Reset branch $mainhead to [string range $rowmenuid 0 7]?" \
+ -justify center -aspect 1000
+ pack $w.m -side top -fill x -padx 20 -pady 20
+ frame $w.f -relief sunken -border 2
+ message $w.f.rt -text "Reset type:" -aspect 1000
+ grid $w.f.rt -sticky w
+ set resettype mixed
+ radiobutton $w.f.soft -value soft -variable resettype -justify left \
+ -text "Soft: Leave working tree and index untouched"
+ grid $w.f.soft -sticky w
+ radiobutton $w.f.mixed -value mixed -variable resettype -justify left \
+ -text "Mixed: Leave working tree untouched, reset index"
+ grid $w.f.mixed -sticky w
+ radiobutton $w.f.hard -value hard -variable resettype -justify left \
+ -text "Hard: Reset working tree and index\n(discard ALL local changes)"
+ grid $w.f.hard -sticky w
+ pack $w.f -side top -fill x
+ button $w.ok -text OK -command "set confirm_ok 1; destroy $w"
+ pack $w.ok -side left -fill x -padx 20 -pady 20
+ button $w.cancel -text Cancel -command "destroy $w"
+ pack $w.cancel -side right -fill x -padx 20 -pady 20
+ bind $w <Visibility> "grab $w; focus $w"
+ tkwait window $w
+ if {!$confirm_ok} return
+ if {[catch {set fd [open \
+ [list | sh -c "git reset --$resettype $rowmenuid 2>&1"] r]} err]} {
+ error_popup $err
+ } else {
+ dohidelocalchanges
+ set w ".resetprogress"
+ filerun $fd [list readresetstat $fd $w]
+ toplevel $w
+ wm transient $w
+ wm title $w "Reset progress"
+ message $w.m -text "Reset in progress, please wait..." \
+ -justify center -aspect 1000
+ pack $w.m -side top -fill x -padx 20 -pady 5
+ canvas $w.c -width 150 -height 20 -bg white
+ $w.c create rect 0 0 0 20 -fill green -tags rect
+ pack $w.c -side top -fill x -padx 20 -pady 5 -expand 1
+ nowbusy reset
+ }
+}
+
+proc readresetstat {fd w} {
+ global mainhead mainheadid showlocalchanges
+
+ if {[gets $fd line] >= 0} {
+ if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
+ set x [expr {($m * 150) / $n}]
+ $w.c coords rect 0 0 $x 20
+ }
+ return 1
+ }
+ destroy $w
+ notbusy reset
+ if {[catch {close $fd} err]} {
+ error_popup $err
+ }
+ set oldhead $mainheadid
+ set newhead [exec git rev-parse HEAD]
+ if {$newhead ne $oldhead} {
+ movehead $newhead $mainhead
+ movedhead $newhead $mainhead
+ set mainheadid $newhead
+ redrawtags $oldhead
+ redrawtags $newhead
+ }
+ if {$showlocalchanges} {
+ doshowlocalchanges
+ }
+ return 0
+}
+
# context menu for a head
proc headmenu {x y id head} {
global headmenuid headmenuhead headctxmenu mainhead
redrawtags $headids($oldmainhead)
}
redrawtags $headmenuid
- if {$showlocalchanges} {
- dodiffindex
- }
+ }
+ if {$showlocalchanges} {
+ dodiffindex
}
}
# coming from descendents, and "outgoing" means going towards ancestors.
proc getallclines {fd} {
- global allids allparents allchildren idtags nextarc nbmp
+ global allids allparents allchildren idtags idheads nextarc nbmp
global arcnos arcids arctags arcout arcend arcstart archeads growing
global seeds allcommits
}
set arcout($id) $ao
}
+ if {$nid > 0} {
+ global cached_dheads cached_dtags cached_atags
+ catch {unset cached_dheads}
+ catch {unset cached_dtags}
+ catch {unset cached_atags}
+ }
if {![eof $fd]} {
return [expr {$nid >= 1000? 2: 1}]
}
# Both are on the same arc(s); either both are the same BMP,
# or if one is not a BMP, the other is also not a BMP or is
# the BMP at end of the arc (and it only has 1 incoming arc).
- if {$a eq $b} {
+ # Or both can be BMPs with no incoming arcs.
+ if {$a eq $b || $arcnos($a) eq {}} {
return 0
}
# assert {[llength $arcnos($a)] == 1}
if {![info exists allparents($id)]} {
return {}
}
- set ret {}
+ set aret {}
if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
# part-way along an arc; check it first
set a [lindex $arcnos($id) 0]
foreach t $archeads($a) {
set j [lsearch -exact $arcids($a) $t]
if {$j > $i} break
- lappend $ret $t
+ lappend aret $t
}
}
set id $arcstart($a)
set origid $id
set todo [list $id]
set seen($id) 1
+ set ret {}
for {set i 0} {$i < [llength $todo]} {incr i} {
set id [lindex $todo $i]
if {[info exists cached_dheads($id)]} {
}
foreach a $arcnos($id) {
if {$archeads($a) ne {}} {
- set ret [concat $ret $archeads($a)]
+ validate_archeads $a
+ if {$archeads($a) ne {}} {
+ set ret [concat $ret $archeads($a)]
+ }
}
set d $arcstart($a)
if {![info exists seen($d)]} {
}
set ret [lsort -unique $ret]
set cached_dheads($origid) $ret
+ return [concat $ret $aret]
}
proc addedtag {id} {
pack $top.ntag.b $top.ntag.l -side left
grid x $top.ntag -sticky w
label $top.tabstopl -text "tabstop" -font optionfont
- entry $top.tabstop -width 10 -textvariable tabstop
+ spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
grid x $top.tabstopl $top.tabstop -sticky w
label $top.cdisp -text "Colors: press to choose"
grid x $top.hunksepbut $top.hunksep -sticky w
label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
button $top.selbgbut -text "Select bg" -font optionfont \
- -command [list choosecolor selectbgcolor 0 $top.bg background setselbg]
+ -command [list choosecolor selectbgcolor 0 $top.selbgsep background setselbg]
grid x $top.selbgbut $top.selbgsep -sticky w
frame $top.buts
set maxwidth 16
set revlistorder 0
set fastdate 0
-set uparrowlen 7
-set downarrowlen 7
-set mingaplen 30
+set uparrowlen 5
+set downarrowlen 5
+set mingaplen 100
set cmitmode "patch"
set wrapcomment "none"
set showneartags 1
font create optionfont -family sans-serif -size -12
-set revtreeargs {}
-foreach arg $argv {
- switch -regexp -- $arg {
- "^$" { }
- "^-d" { set datemode 1 }
- default {
- lappend revtreeargs $arg
- }
- }
-}
-
# check that we can find a .git directory somewhere...
set gitdir [gitdir]
if {![file isdirectory $gitdir]} {
exit 1
}
+set revtreeargs {}
set cmdline_files {}
-set i [lsearch -exact $revtreeargs "--"]
-if {$i >= 0} {
- set cmdline_files [lrange $revtreeargs [expr {$i + 1}] end]
- set revtreeargs [lrange $revtreeargs 0 [expr {$i - 1}]]
-} elseif {$revtreeargs ne {}} {
+set i 0
+foreach arg $argv {
+ switch -- $arg {
+ "" { }
+ "-d" { set datemode 1 }
+ "--" {
+ set cmdline_files [lrange $argv [expr {$i + 1}] end]
+ break
+ }
+ default {
+ lappend revtreeargs $arg
+ }
+ }
+ incr i
+}
+
+if {$i >= [llength $argv] && $revtreeargs ne {}} {
+ # no -- on command line, but some arguments (other than -d)
if {[catch {
set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
set cmdline_files [split $f "\n"]
set n [llength $cmdline_files]
set revtreeargs [lrange $revtreeargs 0 end-$n]
+ # Unfortunately git rev-parse doesn't produce an error when
+ # something is both a revision and a filename. To be consistent
+ # with git log and git rev-list, check revtreeargs for filenames.
+ foreach arg $revtreeargs {
+ if {[file exists $arg]} {
+ show_error {} . "Ambiguous argument '$arg': both revision\
+ and filename"
+ exit 1
+ }
+ }
} err]} {
# unfortunately we get both stdout and stderr in $err,
# so look for "fatal:".
}
set nullid "0000000000000000000000000000000000000000"
+set nullid2 "0000000000000000000000000000000000000001"
+
set runq {}
set history {}
set boldrows {}
set boldnamerows {}
set diffelide {0 0}
+set markingmatches 0
set optim_delay 16
set stuffsaved 0
set patchnum 0
set lookingforhead 0
-set localrow -1
+set localirow -1
+set localfrow -1
set lserial 0
setcoords
makewindow
+# wait for the window to become visible
+tkwait visibility .
wm title . "[file tail $argv0]: [file tail [pwd]]"
readrefs