Browse Source

gitk: Allow view to specify arbitrary arguments to git-rev-list

The list of arguments to git-rev-list, including arguments that
select the range of commits, is now a part of the view specification.
If any arguments are given to gitk, they become part of the
"Command line" view, and the non-file arguments become the default
for any new views created.

Getting an error from git-rev-list is no longer fatal; instead the
error window pops up, and when you press OK, the main window just
shows "No commits selected".

The git-rev-list arguments are entered in an entry widget in the
view editor window using shell quoting conventions, not Tcl quoting
conventions.

Signed-off-by: Paul Mackerras <paulus@samba.org>
maint
Paul Mackerras 19 years ago
parent
commit
098dd8a34b
  1. 247
      gitk

247
gitk

@ -19,13 +19,13 @@ proc gitdir {} {
proc start_rev_list {view} { proc start_rev_list {view} {
global startmsecs nextupdate ncmupdate global startmsecs nextupdate ncmupdate
global commfd leftover tclencoding datemode global commfd leftover tclencoding datemode
global revtreeargs viewfiles commitidx global viewargs viewfiles commitidx


set startmsecs [clock clicks -milliseconds] set startmsecs [clock clicks -milliseconds]
set nextupdate [expr {$startmsecs + 100}] set nextupdate [expr {$startmsecs + 100}]
set ncmupdate 1 set ncmupdate 1
set commitidx($view) 0 set commitidx($view) 0
set args $revtreeargs set args $viewargs($view)
if {$viewfiles($view) ne {}} { if {$viewfiles($view) ne {}} {
set args [concat $args "--" $viewfiles($view)] set args [concat $args "--" $viewfiles($view)]
} }
@ -69,9 +69,7 @@ proc getcommits {} {
set phase getcommits set phase getcommits
initlayout initlayout
start_rev_list $curview start_rev_list $curview
$canv delete all show_status "Reading commits..."
$canv create text 3 3 -anchor nw -text "Reading commits..." \
-font $mainfont -tags textitems
} }


proc getcommitlines {fd view} { proc getcommitlines {fd view} {
@ -84,26 +82,33 @@ proc getcommitlines {fd view} {
set stuff [read $fd] set stuff [read $fd]
if {$stuff == {}} { if {$stuff == {}} {
if {![eof $fd]} return if {![eof $fd]} return
global viewname
unset commfd($view) unset commfd($view)
notbusy $view
# set it blocking so we wait for the process to terminate # set it blocking so we wait for the process to terminate
fconfigure $fd -blocking 1 fconfigure $fd -blocking 1
if {![catch {close $fd} err]} { if {[catch {close $fd} err]} {
notbusy $view set fv {}
if {$view == $curview} { if {$view != $curview} {
after idle finishcommits set fv " for the \"$viewname($view)\" view"
} }
return if {[string range $err 0 4] == "usage"} {
set err "Gitk: error reading commits$fv:\
bad arguments to git-rev-list."
if {$viewname($view) eq "Command line"} {
append err \
" (Note: arguments to gitk are passed to git-rev-list\
to allow selection of commits to be displayed.)"
}
} else {
set err "Error reading commits$fv: $err"
}
error_popup $err
} }
if {[string range $err 0 4] == "usage"} { if {$view == $curview} {
set err \ after idle finishcommits
"Gitk: error reading commits: bad arguments to git-rev-list.\
(Note: arguments to gitk are passed to git-rev-list\
to allow selection of commits to be displayed.)"
} else {
set err "Error reading commits: $err"
} }
error_popup $err return
exit 1
} }
set start 0 set start 0
set gotsome 0 set gotsome 0
@ -217,7 +222,7 @@ proc readcommit {id} {
} }


proc updatecommits {} { proc updatecommits {} {
global viewdata curview revtreeargs phase displayorder global viewdata curview phase displayorder
global children commitrow global children commitrow


if {$phase ne {}} { if {$phase ne {}} {
@ -352,10 +357,7 @@ proc readrefs {} {
close $refd close $refd
} }


proc error_popup msg { proc show_error {w msg} {
set w .error
toplevel $w
wm transient $w .
message $w.m -text $msg -justify center -aspect 400 message $w.m -text $msg -justify center -aspect 400
pack $w.m -side top -fill x -padx 20 -pady 20 pack $w.m -side top -fill x -padx 20 -pady 20
button $w.ok -text OK -command "destroy $w" button $w.ok -text OK -command "destroy $w"
@ -365,6 +367,13 @@ proc error_popup msg {
tkwait window $w tkwait window $w
} }


proc error_popup msg {
set w .error
toplevel $w
wm transient $w .
show_error $w $msg
}

proc makewindow {} { proc makewindow {} {
global canv canv2 canv3 linespc charspc ctext cflist global canv canv2 canv3 linespc charspc ctext cflist
global textfont mainfont uifont global textfont mainfont uifont
@ -686,7 +695,7 @@ proc savestuff {w} {
global canv canv2 canv3 ctext cflist mainfont textfont uifont global canv canv2 canv3 ctext cflist mainfont textfont uifont
global stuffsaved findmergefiles maxgraphpct global stuffsaved findmergefiles maxgraphpct
global maxwidth global maxwidth
global viewname viewfiles viewperm nextviewnum global viewname viewfiles viewargs viewperm nextviewnum
global cmitmode global cmitmode


if {$stuffsaved} return if {$stuffsaved} return
@ -715,7 +724,7 @@ proc savestuff {w} {
puts -nonewline $f "set permviews {" puts -nonewline $f "set permviews {"
for {set v 0} {$v < $nextviewnum} {incr v} { for {set v 0} {$v < $nextviewnum} {incr v} {
if {$viewperm($v)} { if {$viewperm($v)} {
puts $f "{[list $viewname($v) $viewfiles($v)]}" puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v)]}"
} }
} }
puts $f "}" puts $f "}"
@ -1136,10 +1145,105 @@ proc sel_flist {w x y} {
} }
} }


# Functions for adding and removing shell-type quoting

proc shellquote {str} {
if {![string match "*\['\"\\ \t]*" $str]} {
return $str
}
if {![string match "*\['\"\\]*" $str]} {
return "\"$str\""
}
if {![string match "*'*" $str]} {
return "'$str'"
}
return "\"[string map {\" \\\" \\ \\\\} $str]\""
}

proc shellarglist {l} {
set str {}
foreach a $l {
if {$str ne {}} {
append str " "
}
append str [shellquote $a]
}
return $str
}

proc shelldequote {str} {
set ret {}
set used -1
while {1} {
incr used
if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
append ret [string range $str $used end]
set used [string length $str]
break
}
set first [lindex $first 0]
set ch [string index $str $first]
if {$first > $used} {
append ret [string range $str $used [expr {$first - 1}]]
set used $first
}
if {$ch eq " " || $ch eq "\t"} break
incr used
if {$ch eq "'"} {
set first [string first "'" $str $used]
if {$first < 0} {
error "unmatched single-quote"
}
append ret [string range $str $used [expr {$first - 1}]]
set used $first
continue
}
if {$ch eq "\\"} {
if {$used >= [string length $str]} {
error "trailing backslash"
}
append ret [string index $str $used]
continue
}
# here ch == "\""
while {1} {
if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
error "unmatched double-quote"
}
set first [lindex $first 0]
set ch [string index $str $first]
if {$first > $used} {
append ret [string range $str $used [expr {$first - 1}]]
set used $first
}
if {$ch eq "\""} break
incr used
append ret [string index $str $used]
incr used
}
}
return [list $used $ret]
}

proc shellsplit {str} {
set l {}
while {1} {
set str [string trimleft $str]
if {$str eq {}} break
set dq [shelldequote $str]
set n [lindex $dq 0]
set word [lindex $dq 1]
set str [string range $str $n end]
lappend l $word
}
return $l
}

# Code to implement multiple views # Code to implement multiple views


proc newview {ishighlight} { proc newview {ishighlight} {
global nextviewnum newviewname newviewperm uifont newishighlight global nextviewnum newviewname newviewperm uifont newishighlight
global newviewargs revtreeargs


set newishighlight $ishighlight set newishighlight $ishighlight
set top .gitkview set top .gitkview
@ -1149,12 +1253,14 @@ proc newview {ishighlight} {
} }
set newviewname($nextviewnum) "View $nextviewnum" set newviewname($nextviewnum) "View $nextviewnum"
set newviewperm($nextviewnum) 0 set newviewperm($nextviewnum) 0
set newviewargs($nextviewnum) [shellarglist $revtreeargs]
vieweditor $top $nextviewnum "Gitk view definition" vieweditor $top $nextviewnum "Gitk view definition"
} }


proc editview {} { proc editview {} {
global curview global curview
global viewname viewperm newviewname newviewperm global viewname viewperm newviewname newviewperm
global viewargs newviewargs


set top .gitkvedit-$curview set top .gitkvedit-$curview
if {[winfo exists $top]} { if {[winfo exists $top]} {
@ -1163,6 +1269,7 @@ proc editview {} {
} }
set newviewname($curview) $viewname($curview) set newviewname($curview) $viewname($curview)
set newviewperm($curview) $viewperm($curview) set newviewperm($curview) $viewperm($curview)
set newviewargs($curview) [shellarglist $viewargs($curview)]
vieweditor $top $curview "Gitk: edit view $viewname($curview)" vieweditor $top $curview "Gitk: edit view $viewname($curview)"
} }


@ -1177,7 +1284,13 @@ proc vieweditor {top n title} {
grid $top.nl $top.name -sticky w -pady 5 grid $top.nl $top.name -sticky w -pady 5
checkbutton $top.perm -text "Remember this view" -variable newviewperm($n) checkbutton $top.perm -text "Remember this view" -variable newviewperm($n)
grid $top.perm - -pady 5 -sticky w grid $top.perm - -pady 5 -sticky w
message $top.l -aspect 500 -font $uifont \ message $top.al -aspect 1000 -font $uifont \
-text "Commits to include (arguments to git-rev-list):"
grid $top.al - -sticky w -pady 5
entry $top.args -width 50 -textvariable newviewargs($n) \
-background white
grid $top.args - -sticky ew -padx 5
message $top.l -aspect 1000 -font $uifont \
-text "Enter files and directories to include, one per line:" -text "Enter files and directories to include, one per line:"
grid $top.l - -sticky w grid $top.l - -sticky w
text $top.t -width 40 -height 10 -background white text $top.t -width 40 -height 10 -background white
@ -1189,7 +1302,7 @@ proc vieweditor {top n title} {
$top.t delete {end - 1c} end $top.t delete {end - 1c} end
$top.t mark set insert 0.0 $top.t mark set insert 0.0
} }
grid $top.t - -sticky w -padx 5 grid $top.t - -sticky ew -padx 5
frame $top.buts frame $top.buts
button $top.buts.ok -text "OK" -command [list newviewok $top $n] button $top.buts.ok -text "OK" -command [list newviewok $top $n]
button $top.buts.can -text "Cancel" -command [list destroy $top] button $top.buts.can -text "Cancel" -command [list destroy $top]
@ -1211,14 +1324,23 @@ proc doviewmenu {m first cmd op args} {
} }


proc allviewmenus {n op args} { proc allviewmenus {n op args} {
doviewmenu .bar.view 6 [list showview $n] $op $args doviewmenu .bar.view 7 [list showview $n] $op $args
doviewmenu .bar.view.hl 3 [list addhighlight $n] $op $args doviewmenu .bar.view.hl 3 [list addhighlight $n] $op $args
} }


proc newviewok {top n} { proc newviewok {top n} {
global nextviewnum newviewperm newviewname newishighlight global nextviewnum newviewperm newviewname newishighlight
global viewname viewfiles viewperm selectedview curview global viewname viewfiles viewperm selectedview curview
global viewargs newviewargs


if {[catch {
set newargs [shellsplit $newviewargs($n)]
} err]} {
error_popup "Error in commit selection arguments: $err"
wm raise $top
focus $top
return
}
set files {} set files {}
foreach f [split [$top.t get 0.0 end] "\n"] { foreach f [split [$top.t get 0.0 end] "\n"] {
set ft [string trim $f] set ft [string trim $f]
@ -1232,6 +1354,7 @@ proc newviewok {top n} {
set viewname($n) $newviewname($n) set viewname($n) $newviewname($n)
set viewperm($n) $newviewperm($n) set viewperm($n) $newviewperm($n)
set viewfiles($n) $files set viewfiles($n) $files
set viewargs($n) $newargs
addviewmenu $n addviewmenu $n
if {!$newishighlight} { if {!$newishighlight} {
after idle showview $n after idle showview $n
@ -1245,8 +1368,9 @@ proc newviewok {top n} {
set viewname($n) $newviewname($n) set viewname($n) $newviewname($n)
allviewmenus $n entryconf -label $viewname($n) allviewmenus $n entryconf -label $viewname($n)
} }
if {$files ne $viewfiles($n)} { if {$files ne $viewfiles($n) || $newargs ne $viewargs($n)} {
set viewfiles($n) $files set viewfiles($n) $files
set viewargs($n) $newargs
if {$curview == $n} { if {$curview == $n} {
after idle updatecommits after idle updatecommits
} }
@ -1347,8 +1471,8 @@ proc showview {n} {
set curview $n set curview $n
set selectedview $n set selectedview $n
set selectedhlview -1 set selectedhlview -1
.bar.view entryconf 1 -state [expr {$n == 0? "disabled": "normal"}]
.bar.view entryconf 2 -state [expr {$n == 0? "disabled": "normal"}] .bar.view entryconf 2 -state [expr {$n == 0? "disabled": "normal"}]
.bar.view entryconf 3 -state [expr {$n == 0? "disabled": "normal"}]
catch {unset hlview} catch {unset hlview}
.bar.view.hl entryconf 1 -state disabled .bar.view.hl entryconf 1 -state disabled


@ -1403,15 +1527,15 @@ proc showview {n} {
selectline $row 0 selectline $row 0
if {$phase ne {}} { if {$phase ne {}} {
if {$phase eq "getcommits"} { if {$phase eq "getcommits"} {
global mainfont show_status "Reading commits..."
$canv create text 3 3 -anchor nw -text "Reading commits..." \
-font $mainfont -tags textitems
} }
if {[info exists commfd($n)]} { if {[info exists commfd($n)]} {
layoutmore layoutmore
} else { } else {
finishcommits finishcommits
} }
} elseif {$numcommits == 0} {
show_status "No commits selected"
} }
} }


@ -2533,6 +2657,13 @@ proc xcoord {i level ln} {
return $x return $x
} }


proc show_status {msg} {
global canv mainfont

clear_display
$canv create text 3 3 -anchor nw -text $msg -font $mainfont -tags textitems
}

proc finishcommits {} { proc finishcommits {} {
global commitidx phase curview global commitidx phase curview
global canv mainfont ctext maincursor textcursor global canv mainfont ctext maincursor textcursor
@ -2541,9 +2672,7 @@ proc finishcommits {} {
if {$commitidx($curview) > 0} { if {$commitidx($curview) > 0} {
drawrest drawrest
} else { } else {
$canv delete all show_status "No commits selected"
$canv create text 3 3 -anchor nw -text "No commits selected" \
-font $mainfont -tags textitems
} }
set phase {} set phase {}
catch {unset pending_select} catch {unset pending_select}
@ -4782,10 +4911,33 @@ foreach arg $argv {
# check that we can find a .git directory somewhere... # check that we can find a .git directory somewhere...
set gitdir [gitdir] set gitdir [gitdir]
if {![file isdirectory $gitdir]} { if {![file isdirectory $gitdir]} {
error_popup "Cannot find the git directory \"$gitdir\"." show_error . "Cannot find the git directory \"$gitdir\"."
exit 1 exit 1
} }


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 {}} {
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]
} err]} {
# unfortunately we get both stdout and stderr in $err,
# so look for "fatal:".
set i [string first "fatal:" $err]
if {$i > 0} {
set err [string range [expr {$i + 6}] end]
}
show_error . "Bad arguments to gitk:\n$err"
exit 1
}
}

set history {} set history {}
set historyindex 0 set historyindex 0


@ -4797,7 +4949,9 @@ set selectedview 0
set selectedhlview {} set selectedhlview {}
set viewfiles(0) {} set viewfiles(0) {}
set viewperm(0) 0 set viewperm(0) 0
set viewargs(0) {}


set cmdlineok 0
set stopped 0 set stopped 0
set stuffsaved 0 set stuffsaved 0
set patchnum 0 set patchnum 0
@ -4805,28 +4959,18 @@ setcoords
makewindow makewindow
readrefs readrefs


set cmdline_files {} if {$cmdline_files ne {} || $revtreeargs ne {}} {
catch {
set fileargs [eval exec git-rev-parse --no-revs --no-flags $revtreeargs]
set cmdline_files [split $fileargs "\n"]
set n [llength $cmdline_files]
set revtreeargs [lrange $revtreeargs 0 end-$n]
}
if {[lindex $revtreeargs end] eq "--"} {
set revtreeargs [lrange $revtreeargs 0 end-1]
}

if {$cmdline_files ne {}} {
# create a view for the files/dirs specified on the command line # create a view for the files/dirs specified on the command line
set curview 1 set curview 1
set selectedview 1 set selectedview 1
set nextviewnum 2 set nextviewnum 2
set viewname(1) "Command line" set viewname(1) "Command line"
set viewfiles(1) $cmdline_files set viewfiles(1) $cmdline_files
set viewargs(1) $revtreeargs
set viewperm(1) 0 set viewperm(1) 0
addviewmenu 1 addviewmenu 1
.bar.view entryconf 1 -state normal
.bar.view entryconf 2 -state normal .bar.view entryconf 2 -state normal
.bar.view entryconf 3 -state normal
} }


if {[info exists permviews]} { if {[info exists permviews]} {
@ -4835,6 +4979,7 @@ if {[info exists permviews]} {
incr nextviewnum incr nextviewnum
set viewname($n) [lindex $v 0] set viewname($n) [lindex $v 0]
set viewfiles($n) [lindex $v 1] set viewfiles($n) [lindex $v 1]
set viewargs($n) [lindex $v 2]
set viewperm($n) 1 set viewperm($n) 1
addviewmenu $n addviewmenu $n
} }

Loading…
Cancel
Save