X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=gitk;h=ebbeac63aaac66c3ffef53c1d66836c11d22ddbf;hb=cc4c4f0ce25cc3803197bc19c275fd6f59a2a511;hp=596f605868811df9454f3f889294bd76c8792ffd;hpb=53cda8d97e6ee53cc8defa8c7226f0b3093eb12a;p=git.git diff --git a/gitk b/gitk index 596f60586..ebbeac63a 100755 --- a/gitk +++ b/gitk @@ -17,13 +17,12 @@ proc gitdir {} { } 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 {}} { @@ -79,7 +78,7 @@ proc getcommitlines {fd view} { 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 @@ -185,7 +184,7 @@ proc getcommitlines {fd view} { } if {$gotsome} { if {$view == $curview} { - layoutmore + while {[layoutmore $nextupdate]} doupdate } elseif {[info exists hlview] && $view == $hlview} { vhighlightmore } @@ -196,20 +195,13 @@ proc getcommitlines {fd view} { } 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] @@ -730,6 +722,8 @@ proc makewindow {} { $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 @@ -1695,7 +1689,7 @@ proc showview {n} { show_status "Reading commits..." } if {[info exists commfd($n)]} { - layoutmore + layoutmore {} } else { finishcommits } @@ -2376,20 +2370,38 @@ proc visiblerows {} { 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 + } } } @@ -3302,6 +3314,108 @@ proc finishcommits {} { 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} { @@ -3629,27 +3743,20 @@ proc viewnextline {dir} { # 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> \ @@ -3663,6 +3770,18 @@ proc appendrefs {pos l var} { 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 @@ -3672,15 +3791,15 @@ proc dispneartags {} { 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 } @@ -3813,7 +3932,7 @@ proc selectline {l isnew} { $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" } @@ -3822,13 +3941,13 @@ proc selectline {l isnew} { $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" } @@ -4489,6 +4608,7 @@ proc redisplay {} { drawvisible if {[info exists selectedline]} { selectline $selectedline 0 + allcanvs yview moveto [lindex $span 0] } } @@ -4956,6 +5076,7 @@ proc domktag {} { set tagids($tag) $id lappend idtags($id) $tag redrawtags $id + addedtag $id } proc redrawtags {id} { @@ -5090,17 +5211,57 @@ proc mkbrgo {top} { 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 @@ -5142,7 +5303,7 @@ proc rmbranch {} { error_popup "Cannot delete the currently checked-out branch" return } - if {$desc_heads($id) eq $id && $idheads($id) eq [list $head]} { + 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 @@ -5154,16 +5315,7 @@ proc rmbranch {} { 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 } @@ -5293,7 +5445,7 @@ proc forward_pass {id children} { } } if {[info exists idheads($id)]} { - lappend dheads $id + set dheads [concat $dheads $idheads($id)] } set desc_heads($id) $dheads } @@ -5301,7 +5453,7 @@ proc forward_pass {id children} { 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] @@ -5368,18 +5520,97 @@ proc restartatags {} { 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) @@ -5393,15 +5624,25 @@ proc addedhead {hid} { } # 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] @@ -5416,6 +5657,23 @@ proc removedhead {hid} { } } +# 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