1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-10-29 21:37:53 +01:00

gitk: Show local uncommitted changes as a fake commit

If there are local changes in the repository, i.e., git-diff-index HEAD
produces some output, then this optionally displays an extra row in
the graph as a child of the HEAD commit (but with a red circle to
indicate that it's not a real commit).  There is a checkbox in the
preferences window to control whether gitk does this or not.

Clicking on the extra row shows the diffs between the working directory
and the HEAD (using git diff-index -p).  The right-click menu on the
extra row allows the user to generate a patch containing the local diffs,
or to display the diffs between the working directory and any commit.

Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Paul Mackerras 2006-09-07 10:21:39 +10:00
parent 322a8cc9b3
commit 219ea3a99b

335
gitk
View file

@ -83,6 +83,7 @@ proc start_rev_list {view} {
global startmsecs
global commfd leftover tclencoding datemode
global viewargs viewfiles commitidx
global lookingforhead showlocalchanges
set startmsecs [clock clicks -milliseconds]
set commitidx($view) 0
@ -103,6 +104,7 @@ proc start_rev_list {view} {
}
set commfd($view) $fd
set leftover($view) {}
set lookingforhead $showlocalchanges
fconfigure $fd -blocking 0 -translation lf
if {$tclencoding != {}} {
fconfigure $fd -encoding $tclencoding
@ -262,7 +264,7 @@ proc chewcommits {view} {
set tlimit [expr {[clock clicks -milliseconds] + 50}]
set more [layoutmore $tlimit $allread]
if {$allread && !$more} {
global displayorder commitidx phase
global displayorder nullid commitidx phase
global numcommits startmsecs
if {[info exists pending_select]} {
@ -386,7 +388,7 @@ proc getcommit {id} {
proc readrefs {} {
global tagids idtags headids idheads tagcontents
global otherrefids idotherrefs mainhead
global otherrefids idotherrefs mainhead mainheadid
foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
catch {unset $v}
@ -433,10 +435,14 @@ proc readrefs {} {
}
close $refd
set mainhead {}
set mainheadid {}
catch {
set thehead [exec git symbolic-ref HEAD]
if {[string match "refs/heads/*" $thehead]} {
set mainhead [string range $thehead 11 end]
if {[info exists headids($mainhead)]} {
set mainheadid $headids($mainhead)
}
}
}
}
@ -505,7 +511,7 @@ proc makewindow {} {
global findtype findtypemenu findloc findstring fstring geometry
global entries sha1entry sha1string sha1but
global maincursor textcursor curtextcursor
global rowctxmenu mergemax wrapcomment
global rowctxmenu fakerowmenu mergemax wrapcomment
global highlight_files gdttype
global searchstring sstring
global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
@ -878,6 +884,17 @@ proc makewindow {} {
$rowctxmenu add command -label "Cherry-pick this commit" \
-command cherrypick
set fakerowmenu .fakerowmenu
menu $fakerowmenu -tearoff 0
$fakerowmenu add command -label "Diff this -> selected" \
-command {diffvssel 0}
$fakerowmenu add command -label "Diff selected -> this" \
-command {diffvssel 1}
$fakerowmenu add command -label "Make patch" -command mkpatch
# $fakerowmenu add command -label "Commit" -command {mkcommit 0}
# $fakerowmenu add command -label "Commit all" -command {mkcommit 1}
# $fakerowmenu add command -label "Revert local changes" -command revertlocal
set headctxmenu .headctxmenu
menu $headctxmenu -tearoff 0
$headctxmenu add command -label "Check out this branch" \
@ -933,7 +950,7 @@ proc click {w} {
proc savestuff {w} {
global canv canv2 canv3 ctext cflist mainfont textfont uifont tabstop
global stuffsaved findmergefiles maxgraphpct
global maxwidth showneartags
global maxwidth showneartags showlocalchanges
global viewname viewfiles viewargs viewperm nextviewnum
global cmitmode wrapcomment
global colors bgcolor fgcolor diffcolors selectbgcolor
@ -952,6 +969,7 @@ proc savestuff {w} {
puts $f [list set cmitmode $cmitmode]
puts $f [list set wrapcomment $wrapcomment]
puts $f [list set showneartags $showneartags]
puts $f [list set showlocalchanges $showlocalchanges]
puts $f [list set bgcolor $bgcolor]
puts $f [list set fgcolor $fgcolor]
puts $f [list set colors $colors]
@ -1746,7 +1764,7 @@ proc showview {n} {
global curview viewdata viewfiles
global displayorder parentlist childlist rowidlist rowoffsets
global colormap rowtextx commitrow nextcolor canvxmax
global numcommits rowrangelist commitlisted idrowranges
global numcommits rowrangelist commitlisted idrowranges rowchk
global selectedline currentid canv canvy0
global matchinglines treediffs
global pending_select phase
@ -1832,6 +1850,7 @@ proc showview {n} {
set rowlaidout [lindex $v 6]
set rowoptim [lindex $v 7]
set numcommits [lindex $v 8]
catch {unset rowchk}
}
catch {unset colormap}
@ -1861,8 +1880,9 @@ proc showview {n} {
} elseif {$selid ne {}} {
set pending_select $selid
} else {
if {$numcommits > 0} {
selectline 0 0
set row [expr {[lindex $displayorder 0] eq $nullid}]
if {$row < $numcommits} {
selectline $row 0
} else {
set selectfirst 1
}
@ -2559,11 +2579,12 @@ proc layoutmore {tmax allread} {
global rowlaidout rowoptim commitidx numcommits optim_delay
global uparrowlen curview rowidlist idinlist
set showlast 0
set showdelay $optim_delay
set optdelay [expr {$uparrowlen + 1}]
while {1} {
if {$rowoptim - $showdelay > $numcommits} {
showstuff [expr {$rowoptim - $showdelay}]
showstuff [expr {$rowoptim - $showdelay}] $showlast
} elseif {$rowlaidout - $optdelay > $rowoptim} {
set nr [expr {$rowlaidout - $optdelay - $rowoptim}]
if {$nr > 100} {
@ -2592,6 +2613,7 @@ proc layoutmore {tmax allread} {
set rowlaidout $commitidx($curview)
} elseif {$rowoptim == $nrows} {
set showdelay 0
set showlast 1
if {$numcommits == $nrows} {
return 0
}
@ -2605,9 +2627,9 @@ proc layoutmore {tmax allread} {
}
}
proc showstuff {canshow} {
proc showstuff {canshow last} {
global numcommits commitrow pending_select selectedline curview
global displayorder selectfirst
global lookingforhead mainheadid displayorder nullid selectfirst
if {$numcommits == 0} {
global phase
@ -2634,10 +2656,74 @@ proc showstuff {canshow} {
if {[info exists selectedline] || [info exists pending_select]} {
set selectfirst 0
} else {
selectline 0 1
set l [expr {[lindex $displayorder 0] eq $nullid}]
selectline $l 1
set selectfirst 0
}
}
if {$lookingforhead && [info exists commitrow($curview,$mainheadid)]
&& ($last || $commitrow($curview,$mainheadid) < $numcommits - 1)} {
set lookingforhead 0
dodiffindex
}
}
proc doshowlocalchanges {} {
global lookingforhead curview mainheadid phase commitrow
if {[info exists commitrow($curview,$mainheadid)] &&
($phase eq {} || $commitrow($curview,$mainheadid) < $numcommits - 1)} {
dodiffindex
} elseif {$phase ne {}} {
set lookingforhead 1
}
}
proc dohidelocalchanges {} {
global lookingforhead localrow lserial
set lookingforhead 0
if {$localrow >= 0} {
removerow $localrow
set localrow -1
}
incr lserial
}
# spawn off a process to do git diff-index HEAD
proc dodiffindex {} {
global localrow lserial
incr lserial
set localrow -1
set fd [open "|git diff-index HEAD" r]
fconfigure $fd -blocking 0
filerun $fd [list readdiffindex $fd $lserial]
}
proc readdiffindex {fd serial} {
global localrow commitrow mainheadid nullid curview
global commitinfo commitdata lserial
if {[gets $fd line] < 0} {
if {[eof $fd]} {
close $fd
return 0
}
return 1
}
# we only need to see one line and we don't really care what it says...
close $fd
if {$serial == $lserial && $localrow == -1} {
# add the line for the local diff to the graph
set localrow $commitrow($curview,$mainheadid)
set hl "Local uncommitted changes"
set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
set commitdata($nullid) "\n $hl\n"
insertrow $localrow $nullid
}
return 0
}
proc layoutrows {row endrow last} {
@ -2815,7 +2901,7 @@ proc insert_pad {row col npad} {
}
proc optimize_rows {row col endrow} {
global rowidlist rowoffsets idrowranges displayorder
global rowidlist rowoffsets displayorder
for {} {$row < $endrow} {incr row} {
set idlist [lindex $rowidlist $row]
@ -3233,9 +3319,13 @@ proc drawcmittext {id row col} {
global commitlisted commitinfo rowidlist parentlist
global rowtextx idpos idtags idheads idotherrefs
global linehtag linentag linedtag
global mainfont canvxmax boldrows boldnamerows fgcolor
global mainfont canvxmax boldrows boldnamerows fgcolor nullid
set ofill [expr {[lindex $commitlisted $row]? "blue": "white"}]
if {$id eq $nullid} {
set ofill red
} else {
set ofill [expr {[lindex $commitlisted $row]? "blue": "white"}]
}
set x [xc $row $col]
set y [yc $row]
set orad [expr {$linespc / 3}]
@ -3647,10 +3737,10 @@ proc show_status {msg} {
# 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 displayorder parentlist childlist commitlisted children
global commitrow curview rowidlist rowoffsets numcommits
global rowrangelist rowlaidout rowoptim numcommits
global selectedline
global selectedline rowchk commitidx
if {$row >= $numcommits} {
puts "oops, inserting new row $row but only have $numcommits rows"
@ -3663,12 +3753,14 @@ proc insertrow {row newcmit} {
lappend kids $newcmit
lset childlist $row $kids
set childlist [linsert $childlist $row {}]
set children($curview,$p) $kids
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
}
incr commitidx($curview)
set idlist [lindex $rowidlist $row]
set offs [lindex $rowoffsets $row]
@ -3704,6 +3796,8 @@ proc insertrow {row newcmit} {
lset rowrangelist $rp1 $ranges
}
catch {unset rowchk}
incr rowlaidout
incr rowoptim
incr numcommits
@ -3714,6 +3808,67 @@ proc insertrow {row newcmit} {
redisplay
}
# 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 rowrangelist idrowranges rowlaidout rowoptim numcommits
global linesegends selectedline rowchk commitidx
if {$row >= $numcommits} {
puts "oops, removing row $row but only have $numcommits rows"
return
}
set rp1 [expr {$row + 1}]
set id [lindex $displayorder $row]
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 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]
for {set r $row} {$r < $l} {incr r} {
set id [lindex $displayorder $r]
set commitrow($curview,$id) $r
}
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} {
set ranges [lindex $rowrangelist $row]
if {[lindex $ranges end-1] eq $id} {
set ranges [lreplace $ranges end-1 end]
lset rowrangelist $row $ranges
}
}
catch {unset rowchk}
incr rowlaidout -1
incr rowoptim -1
incr numcommits -1
if {[info exists selectedline] && $selectedline > $row} {
incr selectedline -1
}
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} {
@ -4392,13 +4547,18 @@ proc goforw {} {
}
proc gettree {id} {
global treefilelist treeidlist diffids diffmergeid treepending
global treefilelist treeidlist diffids diffmergeid treepending nullid
set diffids $id
catch {unset diffmergeid}
if {![info exists treefilelist($id)]} {
if {![info exists treepending]} {
if {[catch {set gtf [open [concat | git ls-tree -r $id] r]}]} {
if {$id ne $nullid} {
set cmd [concat | git ls-tree -r $id]
} else {
set cmd [concat | git ls-files]
}
if {[catch {set gtf [open $cmd r]}]} {
return
}
set treepending $id
@ -4413,18 +4573,22 @@ proc gettree {id} {
}
proc gettreeline {gtf id} {
global treefilelist treeidlist treepending cmitmode diffids
global treefilelist treeidlist treepending cmitmode diffids nullid
set nl 0
while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
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 {[string index $fname 0] eq "\""} {
set fname [lindex $fname 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 {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
lappend treeidlist($id) $sha1
} else {
set fname $line
}
lappend treeidlist($id) $sha1
lappend treefilelist($id) $fname
}
if {![eof $gtf]} {
@ -4445,7 +4609,7 @@ proc gettreeline {gtf id} {
}
proc showfile {f} {
global treefilelist treeidlist diffids
global treefilelist treeidlist diffids nullid
global ctext commentend
set i [lsearch -exact $treefilelist($diffids) $f]
@ -4453,10 +4617,17 @@ proc showfile {f} {
puts "oops, $f not in list for id $diffids"
return
}
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
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"
return
}
} else {
if {[catch {set bf [open $f r]} err]} {
puts "oops, can't read $f: $err"
return
}
}
fconfigure $bf -blocking 0
filerun $bf [list getblobline $bf $diffids]
@ -4582,11 +4753,11 @@ proc getmergediffline {mdf id np} {
}
proc startdiff {ids} {
global treediffs diffids treepending diffmergeid
global treediffs diffids treepending diffmergeid nullid
set diffids $ids
catch {unset diffmergeid}
if {![info exists treediffs($ids)]} {
if {![info exists treediffs($ids)] || [lsearch -exact $ids $nullid] >= 0} {
if {![info exists treepending]} {
gettreediffs $ids
}
@ -4601,13 +4772,33 @@ proc addtocflist {ids} {
getblobdiffs $ids
}
proc diffcmd {ids flags} {
global nullid
set i [lsearch -exact $ids $nullid]
if {$i >= 0} {
set cmd [concat | git diff-index $flags]
if {[llength $ids] > 1} {
if {$i == 0} {
lappend cmd -R [lindex $ids 1]
} else {
lappend cmd [lindex $ids 0]
}
} else {
lappend cmd HEAD
}
} else {
set cmd [concat | git diff-tree --no-commit-id -r $flags $ids]
}
return $cmd
}
proc gettreediffs {ids} {
global treediff treepending
set treepending $ids
set treediff {}
if {[catch \
{set gdtf [open [concat | git diff-tree --no-commit-id -r $ids] r]} \
]} return
if {[catch {set gdtf [open [diffcmd $ids {}] r]}]} return
fconfigure $gdtf -blocking 0
filerun $gdtf [list gettreediffline $gdtf $ids]
}
@ -4644,8 +4835,7 @@ proc getblobdiffs {ids} {
global diffinhdr treediffs
set env(GIT_DIFF_OPTS) $diffopts
set cmd [concat | git diff-tree --no-commit-id -r -p -C $ids]
if {[catch {set bdf [open $cmd r]} err]} {
if {[catch {set bdf [open [diffcmd $ids {-p -C}] r]} err]} {
puts "error getting diffs: $err"
return
}
@ -5207,19 +5397,25 @@ proc mstime {} {
}
proc rowmenu {x y id} {
global rowctxmenu commitrow selectedline rowmenuid curview
global rowctxmenu commitrow selectedline rowmenuid curview nullid
global fakerowmenu
set rowmenuid $id
if {![info exists selectedline]
|| $commitrow($curview,$id) eq $selectedline} {
set state disabled
} else {
set state normal
}
$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
if {$id ne $nullid} {
set menu $rowctxmenu
} else {
set menu $fakerowmenu
}
$menu entryconfigure "Diff this*" -state $state
$menu entryconfigure "Diff selected*" -state $state
$menu entryconfigure "Make patch" -state $state
tk_popup $menu $x $y
}
proc diffvssel {dirn} {
@ -5330,12 +5526,20 @@ proc mkpatchrev {} {
}
proc mkpatchgo {} {
global patchtop
global patchtop nullid
set oldid [$patchtop.fromsha1 get]
set newid [$patchtop.tosha1 get]
set fname [$patchtop.fname get]
if {[catch {exec git diff-tree -p $oldid $newid >$fname &} err]} {
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]
}
lappend cmd >$fname &
if {[catch {eval exec $cmd} err]} {
error_popup "Error creating patch: $err"
}
catch {destroy $patchtop}
@ -5608,11 +5812,13 @@ proc headmenu {x y id head} {
proc cobranch {} {
global headmenuid headmenuhead mainhead headids
global showlocalchanges mainheadid
# check the tree is clean first??
set oldmainhead $mainhead
nowbusy checkout
update
dohidelocalchanges
if {[catch {
exec git checkout -q $headmenuhead
} err]} {
@ -5621,10 +5827,14 @@ proc cobranch {} {
} else {
notbusy checkout
set mainhead $headmenuhead
set mainheadid $headmenuid
if {[info exists headids($oldmainhead)]} {
redrawtags $headids($oldmainhead)
}
redrawtags $headmenuid
if {$showlocalchanges} {
dodiffindex
}
}
}
@ -6594,7 +6804,7 @@ proc doquit {} {
proc doprefs {} {
global maxwidth maxgraphpct diffopts
global oldprefs prefstop showneartags
global oldprefs prefstop showneartags showlocalchanges
global bgcolor fgcolor ctext diffcolors selectbgcolor
global uifont tabstop
@ -6604,7 +6814,7 @@ proc doprefs {} {
raise $top
return
}
foreach v {maxwidth maxgraphpct diffopts showneartags} {
foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} {
set oldprefs($v) [set $v]
}
toplevel $top
@ -6621,6 +6831,11 @@ proc doprefs {} {
-font optionfont
spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
grid x $top.maxpctl $top.maxpct -sticky w
frame $top.showlocal
label $top.showlocal.l -text "Show local changes" -font optionfont
checkbutton $top.showlocal.b -variable showlocalchanges
pack $top.showlocal.b $top.showlocal.l -side left
grid x $top.showlocal -sticky w
label $top.ddisp -text "Diff display options"
$top.ddisp configure -font $uifont
@ -6723,9 +6938,9 @@ proc setfg {c} {
proc prefscan {} {
global maxwidth maxgraphpct diffopts
global oldprefs prefstop showneartags
global oldprefs prefstop showneartags showlocalchanges
foreach v {maxwidth maxgraphpct diffopts showneartags} {
foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} {
set $v $oldprefs($v)
}
catch {destroy $prefstop}
@ -6734,12 +6949,19 @@ proc prefscan {} {
proc prefsok {} {
global maxwidth maxgraphpct
global oldprefs prefstop showneartags
global oldprefs prefstop showneartags showlocalchanges
global charspc ctext tabstop
catch {destroy $prefstop}
unset prefstop
$ctext configure -tabs "[expr {$tabstop * $charspc}]"
if {$showlocalchanges != $oldprefs(showlocalchanges)} {
if {$showlocalchanges} {
doshowlocalchanges
} else {
dohidelocalchanges
}
}
if {$maxwidth != $oldprefs(maxwidth)
|| $maxgraphpct != $oldprefs(maxgraphpct)} {
redisplay
@ -6749,7 +6971,10 @@ proc prefsok {} {
}
proc formatdate {d} {
return [clock format $d -format "%Y-%m-%d %H:%M:%S"]
if {$d ne {}} {
set d [clock format $d -format "%Y-%m-%d %H:%M:%S"]
}
return $d
}
# This list of encoding names and aliases is distilled from
@ -7059,6 +7284,7 @@ set wrapcomment "none"
set showneartags 1
set maxrefs 20
set maxlinelen 200
set showlocalchanges 1
set colors {green red blue magenta darkgrey brown orange}
set bgcolor white
@ -7111,6 +7337,8 @@ if {$i >= 0} {
}
}
set nullid "0000000000000000000000000000000000000000"
set runq {}
set history {}
set historyindex 0
@ -7136,6 +7364,9 @@ set cmdlineok 0
set stopped 0
set stuffsaved 0
set patchnum 0
set lookingforhead 0
set localrow -1
set lserial 0
setcoords
makewindow
wm title . "[file tail $argv0]: [file tail [pwd]]"