# Tcl ignores the next line -*- tcl -*- \
exec wish "$0" -- "$@"
-# Copyright (C) 2005-2006 Paul Mackerras. All rights reserved.
+# Copyright © 2005-2008 Paul Mackerras. All rights reserved.
# This program is free software; it may be used, copied, modified
# and distributed under the terms of the GNU General Public Licence,
# either version 2, or (at your option) any later version.
}
}
-# Start off a git rev-list process and arrange to read its output
+proc unmerged_files {files} {
+ global nr_unmerged
+
+ # find the list of unmerged files
+ set mlist {}
+ set nr_unmerged 0
+ if {[catch {
+ set fd [open "| git ls-files -u" r]
+ } err]} {
+ show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
+ exit 1
+ }
+ while {[gets $fd line] >= 0} {
+ set i [string first "\t" $line]
+ if {$i < 0} continue
+ set fname [string range $line [expr {$i+1}] end]
+ if {[lsearch -exact $mlist $fname] >= 0} continue
+ incr nr_unmerged
+ if {$files eq {} || [path_filter $files $fname]} {
+ lappend mlist $fname
+ }
+ }
+ catch {close $fd}
+ return $mlist
+}
+
+proc parseviewargs {n arglist} {
+ global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs
+
+ set vdatemode($n) 0
+ set vmergeonly($n) 0
+ set glflags {}
+ set diffargs {}
+ set nextisval 0
+ set revargs {}
+ set origargs $arglist
+ set allknown 1
+ set filtered 0
+ set i -1
+ foreach arg $arglist {
+ incr i
+ if {$nextisval} {
+ lappend glflags $arg
+ set nextisval 0
+ continue
+ }
+ switch -glob -- $arg {
+ "-d" -
+ "--date-order" {
+ set vdatemode($n) 1
+ # remove from origargs in case we hit an unknown option
+ set origargs [lreplace $origargs $i $i]
+ incr i -1
+ }
+ # These request or affect diff output, which we don't want.
+ # Some could be used to set our defaults for diff display.
+ "-[puabwcrRBMC]" -
+ "--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
+ "--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
+ "--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
+ "-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
+ "--ignore-space-change" - "-U*" - "--unified=*" {
+ lappend diffargs $arg
+ }
+ # These cause our parsing of git log's output to fail, or else
+ # they're options we want to set ourselves, so ignore them.
+ "--raw" - "--patch-with-raw" - "--patch-with-stat" -
+ "--name-only" - "--name-status" - "--color" - "--color-words" -
+ "--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
+ "--cc" - "-z" - "--header" - "--parents" - "--boundary" -
+ "--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
+ "--timestamp" - "relative-date" - "--date=*" - "--stdin" -
+ "--objects" - "--objects-edge" - "--reverse" {
+ }
+ # These are harmless, and some are even useful
+ "--stat=*" - "--numstat" - "--shortstat" - "--summary" -
+ "--check" - "--exit-code" - "--quiet" - "--topo-order" -
+ "--full-history" - "--dense" - "--sparse" -
+ "--follow" - "--left-right" - "--encoding=*" {
+ lappend glflags $arg
+ }
+ # These mean that we get a subset of the commits
+ "--diff-filter=*" - "--no-merges" - "--unpacked" -
+ "--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
+ "--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
+ "--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
+ "--remove-empty" - "--first-parent" - "--cherry-pick" -
+ "-S*" - "--pickaxe-all" - "--pickaxe-regex" - {
+ set filtered 1
+ lappend glflags $arg
+ }
+ # This appears to be the only one that has a value as a
+ # separate word following it
+ "-n" {
+ set filtered 1
+ set nextisval 1
+ lappend glflags $arg
+ }
+ "--not" {
+ set notflag [expr {!$notflag}]
+ lappend revargs $arg
+ }
+ "--all" {
+ lappend revargs $arg
+ }
+ "--merge" {
+ set vmergeonly($n) 1
+ # git rev-parse doesn't understand --merge
+ lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
+ }
+ # Other flag arguments including -<n>
+ "-*" {
+ if {[string is digit -strict [string range $arg 1 end]]} {
+ set filtered 1
+ } else {
+ # a flag argument that we don't recognize;
+ # that means we can't optimize
+ set allknown 0
+ }
+ lappend glflags $arg
+ }
+ # Non-flag arguments specify commits or ranges of commits
+ default {
+ if {[string match "*...*" $arg]} {
+ lappend revargs --gitk-symmetric-diff-marker
+ }
+ lappend revargs $arg
+ }
+ }
+ }
+ set vdflags($n) $diffargs
+ set vflags($n) $glflags
+ set vrevs($n) $revargs
+ set vfiltered($n) $filtered
+ set vorigargs($n) $origargs
+ return $allknown
+}
+
+proc parseviewrevs {view revs} {
+ global vposids vnegids
+
+ if {$revs eq {}} {
+ set revs HEAD
+ }
+ if {[catch {set ids [eval exec git rev-parse $revs]} err]} {
+ # we get stdout followed by stderr in $err
+ # for an unknown rev, git rev-parse echoes it and then errors out
+ set errlines [split $err "\n"]
+ set badrev {}
+ for {set l 0} {$l < [llength $errlines]} {incr l} {
+ set line [lindex $errlines $l]
+ if {!([string length $line] == 40 && [string is xdigit $line])} {
+ if {[string match "fatal:*" $line]} {
+ if {[string match "fatal: ambiguous argument*" $line]
+ && $badrev ne {}} {
+ if {[llength $badrev] == 1} {
+ set err "unknown revision $badrev"
+ } else {
+ set err "unknown revisions: [join $badrev ", "]"
+ }
+ } else {
+ set err [join [lrange $errlines $l end] "\n"]
+ }
+ break
+ }
+ lappend badrev $line
+ }
+ }
+ error_popup "Error parsing revisions: $err"
+ return {}
+ }
+ set ret {}
+ set pos {}
+ set neg {}
+ set sdm 0
+ foreach id [split $ids "\n"] {
+ if {$id eq "--gitk-symmetric-diff-marker"} {
+ set sdm 4
+ } elseif {[string match "^*" $id]} {
+ if {$sdm != 1} {
+ lappend ret $id
+ if {$sdm == 3} {
+ set sdm 0
+ }
+ }
+ lappend neg [string range $id 1 end]
+ } else {
+ if {$sdm != 2} {
+ lappend ret $id
+ } else {
+ lset ret end [lindex $ret end]...$id
+ }
+ lappend pos $id
+ }
+ incr sdm -1
+ }
+ set vposids($view) $pos
+ set vnegids($view) $neg
+ return $ret
+}
+
+# Start off a git log process and arrange to read its output
proc start_rev_list {view} {
- global startmsecs
- global commfd leftover tclencoding datemode
- global viewargs viewfiles commitidx viewcomplete vnextroot
+ global startmsecs commitidx viewcomplete
+ global commfd leftover tclencoding
+ global viewargs viewargscmd viewfiles vfilelimit
global showlocalchanges commitinterest mainheadid
global progressdirn progresscoords proglastnc curview
- global viewincl viewactive loginstance viewinstances
+ global viewactive loginstance viewinstances vmergeonly
global pending_select mainheadid
+ global vcanopt vflags vrevs vorigargs
set startmsecs [clock clicks -milliseconds]
set commitidx($view) 0
- set viewcomplete($view) 0
- set viewactive($view) 1
- set vnextroot($view) 0
+ # these are set this way for the error exits
+ set viewcomplete($view) 1
+ set viewactive($view) 0
varcinit $view
- set commits [eval exec git rev-parse --default HEAD --revs-only \
- $viewargs($view)]
- set viewincl($view) {}
- foreach c $commits {
- if {[regexp {^[0-9a-fA-F]{40}$} $c]} {
- lappend viewincl($view) $c
+ set args $viewargs($view)
+ if {$viewargscmd($view) ne {}} {
+ if {[catch {
+ set str [exec sh -c $viewargscmd($view)]
+ } err]} {
+ error_popup "Error executing --argscmd command: $err"
+ return 0
}
+ set args [concat $args [split $str "\n"]]
}
+ set vcanopt($view) [parseviewargs $view $args]
+
+ set files $viewfiles($view)
+ if {$vmergeonly($view)} {
+ set files [unmerged_files $files]
+ if {$files eq {}} {
+ global nr_unmerged
+ if {$nr_unmerged == 0} {
+ error_popup [mc "No files selected: --merge specified but\
+ no files are unmerged."]
+ } else {
+ error_popup [mc "No files selected: --merge specified but\
+ no unmerged files are within file limit."]
+ }
+ return 0
+ }
+ }
+ set vfilelimit($view) $files
+
+ if {$vcanopt($view)} {
+ set revs [parseviewrevs $view $vrevs($view)]
+ if {$revs eq {}} {
+ return 0
+ }
+ set args [concat $vflags($view) $revs]
+ } else {
+ set args $vorigargs($view)
+ }
+
if {[catch {
set fd [open [concat | git log --no-color -z --pretty=raw --parents \
- --boundary $commits "--" $viewfiles($view)] r]
+ --boundary $args "--" $files] r]
} err]} {
error_popup "[mc "Error executing git log:"] $err"
- exit 1
+ return 0
}
set i [incr loginstance]
set viewinstances($view) [list $i]
if {$tclencoding != {}} {
fconfigure $fd -encoding $tclencoding
}
- filerun $fd [list getcommitlines $fd $i $view]
+ filerun $fd [list getcommitlines $fd $i $view 0]
nowbusy $view [mc "Reading"]
if {$view == $curview} {
set progressdirn 1
set proglastnc 0
set pending_select $mainheadid
}
+ set viewcomplete($view) 0
+ set viewactive($view) 1
+ return 1
}
proc stop_rev_list {view} {
}
proc getcommits {} {
- global canv curview
+ global canv curview need_redisplay viewactive
initlayout
- start_rev_list $curview
- show_status [mc "Reading commits..."]
+ if {[start_rev_list $curview]} {
+ show_status [mc "Reading commits..."]
+ set need_redisplay 1
+ } else {
+ show_status [mc "No commits selected"]
+ }
}
proc updatecommits {} {
- global curview viewargs viewfiles viewincl viewinstances
+ global curview vcanopt vorigargs vfilelimit viewinstances
global viewactive viewcomplete loginstance tclencoding mainheadid
- global varcid startmsecs commfd showneartags showlocalchanges leftover
+ global startmsecs commfd showneartags showlocalchanges leftover
global mainheadid pending_select
+ global isworktree
+ global varcid vposids vnegids vflags vrevs
+ set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
set oldmainid $mainheadid
rereadrefs
if {$showlocalchanges} {
}
}
set view $curview
- set commits [exec git rev-parse --default HEAD --revs-only \
- $viewargs($view)]
- set pos {}
- set neg {}
- set flags {}
- foreach c $commits {
- if {[string match "^*" $c]} {
- lappend neg $c
- } elseif {[regexp {^[0-9a-fA-F]{40}$} $c]} {
- if {!([info exists varcid($view,$c)] ||
- [lsearch -exact $viewincl($view) $c] >= 0)} {
- lappend pos $c
+ if {$vcanopt($view)} {
+ set oldpos $vposids($view)
+ set oldneg $vnegids($view)
+ set revs [parseviewrevs $view $vrevs($view)]
+ if {$revs eq {}} {
+ return
+ }
+ # note: getting the delta when negative refs change is hard,
+ # and could require multiple git log invocations, so in that
+ # case we ask git log for all the commits (not just the delta)
+ if {$oldneg eq $vnegids($view)} {
+ set newrevs {}
+ set npos 0
+ # take out positive refs that we asked for before or
+ # that we have already seen
+ foreach rev $revs {
+ if {[string length $rev] == 40} {
+ if {[lsearch -exact $oldpos $rev] < 0
+ && ![info exists varcid($view,$rev)]} {
+ lappend newrevs $rev
+ incr npos
+ }
+ } else {
+ lappend $newrevs $rev
+ }
}
- } else {
- lappend flags $c
+ if {$npos == 0} return
+ set revs $newrevs
+ set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
}
+ set args [concat $vflags($view) $revs --not $oldpos]
+ } else {
+ set args $vorigargs($view)
}
- if {$pos eq {}} {
- return
- }
- foreach id $viewincl($view) {
- lappend neg "^$id"
- }
- set viewincl($view) [concat $viewincl($view) $pos]
if {[catch {
set fd [open [concat | git log --no-color -z --pretty=raw --parents \
- --boundary $pos $neg $flags "--" $viewfiles($view)] r]
+ --boundary $args "--" $vfilelimit($view)] r]
} err]} {
error_popup "Error executing git log: $err"
- exit 1
+ return
}
if {$viewactive($view) == 0} {
set startmsecs [clock clicks -milliseconds]
if {$tclencoding != {}} {
fconfigure $fd -encoding $tclencoding
}
- filerun $fd [list getcommitlines $fd $i $view]
+ filerun $fd [list getcommitlines $fd $i $view 1]
incr viewactive($view)
set viewcomplete($view) 0
set pending_select $mainheadid
catch {unset ordertok}
}
+# returns a list of the commits with no children
+proc seeds {v} {
+ global vdownptr vleftptr varcstart
+
+ set ret {}
+ set a [lindex $vdownptr($v) 0]
+ while {$a != 0} {
+ lappend ret [lindex $varcstart($v) $a]
+ set a [lindex $vleftptr($v) $a]
+ }
+ return $ret
+}
+
proc newvarc {view id} {
- global varcid varctok parents children datemode
+ global varcid varctok parents children vdatemode
global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
global commitdata commitinfo vseedcount varccommits vlastins
set a [llength $varctok($view)]
set vid $view,$id
- if {[llength $children($vid)] == 0 || $datemode} {
+ if {[llength $children($vid)] == 0 || $vdatemode($view)} {
if {![info exists commitinfo($id)]} {
parsecommit $id $commitdata($id) 1
}
proc renumbervarc {a v} {
global parents children varctok varcstart varccommits
- global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod datemode
+ global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
set t1 [clock clicks -milliseconds]
set todo {}
$children($v,$id)]
}
set oldtok [lindex $varctok($v) $a]
- if {!$datemode} {
+ if {!$vdatemode($v)} {
set tok {}
} else {
set tok $oldtok
#puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
}
+# Fix up the graph after we have found out that in view $v,
+# $p (a commit that we have already seen) is actually the parent
+# of the last commit in arc $a.
proc fix_reversal {p a v} {
global varcid varcstart varctok vupptr
set numcommits [incr commitidx($v)]
# note we deliberately don't update varcstart($v) even if $i == 0
set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
- if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
- modify_arc $v $a $i
- }
+ modify_arc $v $a $i
if {[info exists targetid]} {
if {![comes_before $targetid $p]} {
incr targetrow
if {$j >= 0} {
set children($v,$p) [lreplace $children($v,$p) $j $j]
}
- if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
- modify_arc $v $a $i
- }
+ modify_arc $v $a $i
if {[info exist currentid] && $id eq $currentid} {
unset currentid
unset selectedline
[lindex $varctok($v) $varcid($v,$b)]]
}
+# This assumes that if lim is not given, the caller has checked that
+# arc a's token is less than $vtokmod($v)
proc modify_arc {v a {lim {}}} {
global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
+ if {$lim ne {}} {
+ set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
+ if {$c > 0} return
+ if {$c == 0} {
+ set r [lindex $varcrow($v) $a]
+ if {$r ne {} && $vrowmod($v) <= $r + $lim} return
+ }
+ }
set vtokmod($v) [lindex $varctok($v) $a]
set varcmod($v) $a
if {$v == $curview} {
global vupptr vdownptr vleftptr varctok
global displayorder parentlist curview cached_commitrow
+ if {$vrowmod($v) == $commitidx($v)} return
+ if {$v == $curview} {
+ if {[llength $displayorder] > $vrowmod($v)} {
+ set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
+ set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
+ }
+ catch {unset cached_commitrow}
+ }
set narctot [expr {[llength $varctok($v)] - 1}]
set a $varcmod($v)
while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
set row 0
} else {
set arcn [lindex $varcix($v) $a]
- # see if a is the last arc; if so, nothing to do
- if {$arcn == $narctot - 1} {
- return
- }
if {[llength $vrownum($v)] > $arcn + 1} {
set vrownum($v) [lrange $vrownum($v) 0 $arcn]
set varcorder($v) [lrange $varcorder($v) 0 $arcn]
}
set row [lindex $varcrow($v) $a]
}
- if {$v == $curview} {
- if {[llength $displayorder] > $vrowmod($v)} {
- set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
- set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
- }
- catch {unset cached_commitrow}
- }
while {1} {
set p $a
incr row [llength $varccommits($v,$a)]
}
}
-proc getcommitlines {fd inst view} {
+# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
+# Assumes we already have an arc for $rwid.
+proc rewrite_commit {v id rwid} {
+ global children parents varcid varctok vtokmod varccommits
+
+ foreach ch $children($v,$id) {
+ # make $rwid be $ch's parent in place of $id
+ set i [lsearch -exact $parents($v,$ch) $id]
+ if {$i < 0} {
+ puts "oops rewrite_commit didn't find $id in parent list for $ch"
+ }
+ set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
+ # add $ch to $rwid's children and sort the list if necessary
+ if {[llength [lappend children($v,$rwid) $ch]] > 1} {
+ set children($v,$rwid) [lsort -command [list vtokcmp $v] \
+ $children($v,$rwid)]
+ }
+ # fix the graph after joining $id to $rwid
+ set a $varcid($v,$ch)
+ fix_reversal $rwid $a $v
+ # parentlist is wrong for the last element of arc $a
+ # even if displayorder is right, hence the 3rd arg here
+ modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
+ }
+}
+
+proc getcommitlines {fd inst view updating} {
global cmitlisted commitinterest leftover
- global commitidx commitdata datemode
+ global commitidx commitdata vdatemode
global parents children curview hlview
- global vnextroot idpending ordertok
- global varccommits varcid varctok vtokmod
+ global idpending ordertok
+ global varccommits varcid varctok vtokmod vfilelimit
set stuff [read $fd 500000]
# git log doesn't terminate the last commit with a null...
}
if {[string range $err 0 4] == "usage"} {
set err "Gitk: error reading commits$fv:\
- bad arguments to git rev-list."
+ bad arguments to git log."
if {$viewname($view) eq "Command line"} {
append err \
- " (Note: arguments to gitk are passed to git rev-list\
+ " (Note: arguments to gitk are passed to git log\
to allow selection of commits to be displayed.)"
}
} else {
adjustprogress
}
if {$view == $curview} {
- run chewcommits $view
+ run chewcommits
}
return 0
}
}
set id [lindex $ids 0]
set vid $view,$id
+
+ if {!$listed && $updating && ![info exists varcid($vid)] &&
+ $vfilelimit($view) ne {}} {
+ # git log doesn't rewrite parents for unlisted commits
+ # when doing path limiting, so work around that here
+ # by working out the rewritten parent with git rev-list
+ # and if we already know about it, using the rewritten
+ # parent as a substitute parent for $id's children.
+ if {![catch {
+ set rwid [exec git rev-list --first-parent --max-count=1 \
+ $id -- $vfilelimit($view)]
+ }]} {
+ if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
+ # use $rwid in place of $id
+ rewrite_commit $view $id $rwid
+ continue
+ }
+ }
+ }
+
set a 0
if {[info exists varcid($vid)]} {
if {$cmitlisted($vid) || !$listed} continue
} elseif {$a == 0 && [llength $children($vid)] == 1} {
set k [lindex $children($vid) 0]
if {[llength $parents($view,$k)] == 1 &&
- (!$datemode ||
+ (!$vdatemode($view) ||
$varcid($view,$k) == [llength $varctok($view)] - 1)} {
set a $varcid($view,$k)
}
set gotsome 1
}
if {$gotsome} {
- run chewcommits $view
+ global numcommits hlview
+
+ if {$view == $curview} {
+ set numcommits $commitidx($view)
+ run chewcommits
+ }
+ if {[info exists hlview] && $view == $hlview} {
+ # we never actually get here...
+ run vhighlightmore
+ }
foreach s $scripts {
eval $s
}
return 2
}
-proc chewcommits {view} {
+proc chewcommits {} {
global curview hlview viewcomplete
global pending_select
- if {$view == $curview} {
- layoutmore
- if {$viewcomplete($view)} {
- global commitidx varctok
- global numcommits startmsecs
- global mainheadid commitinfo nullid
-
- if {[info exists pending_select]} {
- set row [first_real_row]
- selectline $row 1
- }
- if {$commitidx($curview) > 0} {
- #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
- #puts "overall $ms ms for $numcommits commits"
- #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
- } else {
- show_status [mc "No commits selected"]
- }
- notbusy layout
+ layoutmore
+ if {$viewcomplete($curview)} {
+ global commitidx varctok
+ global numcommits startmsecs
+ global mainheadid nullid
+
+ if {[info exists pending_select]} {
+ set row [first_real_row]
+ selectline $row 1
}
- }
- if {[info exists hlview] && $view == $hlview} {
- vhighlightmore
+ if {$commitidx($curview) > 0} {
+ #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
+ #puts "overall $ms ms for $numcommits commits"
+ #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
+ } else {
+ show_status [mc "No commits selected"]
+ }
+ notbusy layout
}
return 0
}
set headline [string trimright [string range $headline 0 $i]]
}
if {!$listed} {
- # git rev-list indents the comment by 4 spaces;
+ # git log indents the comment by 4 spaces;
# if we got this via git cat-file, add the indentation
set newcomment {}
foreach line [split $comment "\n"] {
}
frame .bleft.top
frame .bleft.mid
+ frame .bleft.bottom
button .bleft.top.search -text [mc "Search"] -command dosearch
pack .bleft.top.search -side left -padx 5
checkbutton .bleft.mid.ignspace -text [mc "Ignore space change"] \
-command changeignorespace -variable ignorespace
pack .bleft.mid.ignspace -side left -padx 5
- set ctext .bleft.ctext
+ set ctext .bleft.bottom.ctext
text $ctext -background $bgcolor -foreground $fgcolor \
-state disabled -font textfont \
- -yscrollcommand scrolltext -wrap none
+ -yscrollcommand scrolltext -wrap none \
+ -xscrollcommand ".bleft.bottom.sbhorizontal set"
if {$have_tk85} {
$ctext conf -tabstyle wordprocessor
}
- scrollbar .bleft.sb -command "$ctext yview"
+ scrollbar .bleft.bottom.sb -command "$ctext yview"
+ scrollbar .bleft.bottom.sbhorizontal -command "$ctext xview" -orient h \
+ -width 10
pack .bleft.top -side top -fill x
pack .bleft.mid -side top -fill x
- pack .bleft.sb -side right -fill y
- pack $ctext -side left -fill both -expand 1
+ grid $ctext .bleft.bottom.sb -sticky nsew
+ grid .bleft.bottom.sbhorizontal -sticky ew
+ grid columnconfigure .bleft.bottom 0 -weight 1
+ grid rowconfigure .bleft.bottom 0 -weight 1
+ grid rowconfigure .bleft.bottom 1 -weight 0
+ pack .bleft.bottom -side top -fill both -expand 1
lappend bglist $ctext
lappend fglist $ctext
.pwbottom add .bright
.ctop add .pwbottom
- # restore window position if known
+ # restore window width & height if known
if {[info exists geometry(main)]} {
- wm geometry . "$geometry(main)"
+ if {[scan $geometry(main) "%dx%d" w h] >= 2} {
+ if {$w > [winfo screenwidth .]} {
+ set w [winfo screenwidth .]
+ }
+ if {$h > [winfo screenheight .]} {
+ set h [winfo screenheight .]
+ }
+ wm geometry . "${w}x$h"
+ }
}
if {[tk windowingsystem] eq {aqua}} {
bindkey k "selnextline 1"
bindkey j "goback"
bindkey l "goforw"
- bindkey b "$ctext yview scroll -1 pages"
+ bindkey b prevfile
bindkey d "$ctext yview scroll 18 units"
bindkey u "$ctext yview scroll -18 units"
bindkey / {dofind 1 1}
-command {flist_hl 0}
$flist_menu add command -label [mc "Highlight this only"] \
-command {flist_hl 1}
+ $flist_menu add command -label [mc "External diff"] \
+ -command {external_diff}
}
# Windows sends all mouse wheel events to the current focused window, not
global canv canv2 canv3 mainfont textfont uifont tabstop
global stuffsaved findmergefiles maxgraphpct
global maxwidth showneartags showlocalchanges
- global viewname viewfiles viewargs viewperm nextviewnum
+ global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
global cmitmode wrapcomment datetimeformat limitdiffs
global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
+ global autoselect extdifftool
if {$stuffsaved} return
if {![winfo viewable .]} return
puts $f [list set maxwidth $maxwidth]
puts $f [list set cmitmode $cmitmode]
puts $f [list set wrapcomment $wrapcomment]
+ puts $f [list set autoselect $autoselect]
puts $f [list set showneartags $showneartags]
puts $f [list set showlocalchanges $showlocalchanges]
puts $f [list set datetimeformat $datetimeformat]
puts $f [list set diffcolors $diffcolors]
puts $f [list set diffcontext $diffcontext]
puts $f [list set selectbgcolor $selectbgcolor]
+ puts $f [list set extdifftool $extdifftool]
puts $f "set geometry(main) [wm geometry .]"
puts $f "set geometry(topwidth) [winfo width .tf]"
puts -nonewline $f "set permviews {"
for {set v 0} {$v < $nextviewnum} {incr v} {
if {$viewperm($v)} {
- puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v)]}"
+ puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v) $viewargscmd($v)]}"
}
}
puts $f "}"
message $w.m -text [mc "
Gitk - a commit viewer for git
-Copyright © 2005-2006 Paul Mackerras
+Copyright © 2005-2008 Paul Mackerras
Use and redistribute under the terms of the GNU General Public License"] \
-justify center -aspect 400 -border 2 -bg white -relief groove
set e [lindex $treediffs($diffids) [expr {$l-2}]]
}
set flist_menu_file $e
+ set xdiffstate "normal"
+ if {$cmitmode eq "tree"} {
+ set xdiffstate "disabled"
+ }
+ # Disable "External diff" item in tree mode
+ $flist_menu entryconf 2 -state $xdiffstate
tk_popup $flist_menu $X $Y
}
set gdttype [mc "touching paths:"]
}
+proc save_file_from_commit {filename output what} {
+ global nullfile
+
+ if {[catch {exec git show $filename -- > $output} err]} {
+ if {[string match "fatal: bad revision *" $err]} {
+ return $nullfile
+ }
+ error_popup "Error getting \"$filename\" from $what: $err"
+ return {}
+ }
+ return $output
+}
+
+proc external_diff_get_one_file {diffid filename diffdir} {
+ global nullid nullid2 nullfile
+ global gitdir
+
+ if {$diffid == $nullid} {
+ set difffile [file join [file dirname $gitdir] $filename]
+ if {[file exists $difffile]} {
+ return $difffile
+ }
+ return $nullfile
+ }
+ if {$diffid == $nullid2} {
+ set difffile [file join $diffdir "\[index\] [file tail $filename]"]
+ return [save_file_from_commit :$filename $difffile index]
+ }
+ set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
+ return [save_file_from_commit $diffid:$filename $difffile \
+ "revision $diffid"]
+}
+
+proc external_diff {} {
+ global gitktmpdir nullid nullid2
+ global flist_menu_file
+ global diffids
+ global diffnum
+ global gitdir extdifftool
+
+ if {[llength $diffids] == 1} {
+ # no reference commit given
+ set diffidto [lindex $diffids 0]
+ if {$diffidto eq $nullid} {
+ # diffing working copy with index
+ set diffidfrom $nullid2
+ } elseif {$diffidto eq $nullid2} {
+ # diffing index with HEAD
+ set diffidfrom "HEAD"
+ } else {
+ # use first parent commit
+ global parentlist selectedline
+ set diffidfrom [lindex $parentlist $selectedline 0]
+ }
+ } else {
+ set diffidfrom [lindex $diffids 0]
+ set diffidto [lindex $diffids 1]
+ }
+
+ # make sure that several diffs wont collide
+ if {![info exists gitktmpdir]} {
+ set gitktmpdir [file join [file dirname $gitdir] \
+ [format ".gitk-tmp.%s" [pid]]]
+ if {[catch {file mkdir $gitktmpdir} err]} {
+ error_popup "Error creating temporary directory $gitktmpdir: $err"
+ unset gitktmpdir
+ return
+ }
+ set diffnum 0
+ }
+ incr diffnum
+ set diffdir [file join $gitktmpdir $diffnum]
+ if {[catch {file mkdir $diffdir} err]} {
+ error_popup "Error creating temporary directory $diffdir: $err"
+ return
+ }
+
+ # gather files to diff
+ set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
+ set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
+
+ if {$difffromfile ne {} && $difftofile ne {}} {
+ set cmd [concat | [shellsplit $extdifftool] \
+ [list $difffromfile $difftofile]]
+ if {[catch {set fl [open $cmd r]} err]} {
+ file delete -force $diffdir
+ error_popup [mc "$extdifftool: command failed: $err"]
+ } else {
+ fconfigure $fl -blocking 0
+ filerun $fl [list delete_at_eof $fl $diffdir]
+ }
+ }
+}
+
+# delete $dir when we see eof on $f (presumably because the child has exited)
+proc delete_at_eof {f dir} {
+ while {[gets $f line] >= 0} {}
+ if {[eof $f]} {
+ if {[catch {close $f} err]} {
+ error_popup "External diff viewer failed: $err"
+ }
+ file delete -force $dir
+ return 0
+ }
+ return 1
+}
+
# Functions for adding and removing shell-type quoting
proc shellquote {str} {
proc newview {ishighlight} {
global nextviewnum newviewname newviewperm newishighlight
- global newviewargs revtreeargs
+ global newviewargs revtreeargs viewargscmd newviewargscmd curview
set newishighlight $ishighlight
set top .gitkview
raise $top
return
}
- set newviewname($nextviewnum) "View $nextviewnum"
+ set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
set newviewperm($nextviewnum) 0
set newviewargs($nextviewnum) [shellarglist $revtreeargs]
+ set newviewargscmd($nextviewnum) $viewargscmd($curview)
vieweditor $top $nextviewnum [mc "Gitk view definition"]
}
proc editview {} {
global curview
global viewname viewperm newviewname newviewperm
- global viewargs newviewargs
+ global viewargs newviewargs viewargscmd newviewargscmd
set top .gitkvedit-$curview
if {[winfo exists $top]} {
set newviewname($curview) $viewname($curview)
set newviewperm($curview) $viewperm($curview)
set newviewargs($curview) [shellarglist $viewargs($curview)]
+ set newviewargscmd($curview) $viewargscmd($curview)
vieweditor $top $curview "Gitk: edit view $viewname($curview)"
}
-variable newviewperm($n)
grid $top.perm - -pady 5 -sticky w
message $top.al -aspect 1000 \
- -text [mc "Commits to include (arguments to git rev-list):"]
+ -text [mc "Commits to include (arguments to git log):"]
grid $top.al - -sticky w -pady 5
entry $top.args -width 50 -textvariable newviewargs($n) \
-background $bgcolor
grid $top.args - -sticky ew -padx 5
+
+ message $top.ac -aspect 1000 \
+ -text [mc "Command to generate more commits to include:"]
+ grid $top.ac - -sticky w -pady 5
+ entry $top.argscmd -width 50 -textvariable newviewargscmd($n) \
+ -background white
+ grid $top.argscmd - -sticky ew -padx 5
+
message $top.l -aspect 1000 \
-text [mc "Enter files and directories to include, one per line:"]
grid $top.l - -sticky w
proc newviewok {top n} {
global nextviewnum newviewperm newviewname newishighlight
global viewname viewfiles viewperm selectedview curview
- global viewargs newviewargs viewhlmenu
+ global viewargs newviewargs viewargscmd newviewargscmd viewhlmenu
if {[catch {
set newargs [shellsplit $newviewargs($n)]
set viewperm($n) $newviewperm($n)
set viewfiles($n) $files
set viewargs($n) $newargs
+ set viewargscmd($n) $newviewargscmd($n)
addviewmenu $n
if {!$newishighlight} {
run showview $n
# doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
# entryconf [list -label $viewname($n) -value $viewname($n)]
}
- if {$files ne $viewfiles($n) || $newargs ne $viewargs($n)} {
+ if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
+ $newviewargscmd($n) ne $viewargscmd($n)} {
set viewfiles($n) $files
set viewargs($n) $newargs
+ set viewargscmd($n) $newviewargscmd($n)
if {$curview == $n} {
run reloadcommits
}
}
proc showview {n} {
- global curview viewfiles cached_commitrow ordertok
+ global curview cached_commitrow ordertok
global displayorder parentlist rowidlist rowisopt rowfinal
global colormap rowtextx nextcolor canvxmax
global numcommits viewcomplete
}
}
set vhl_done $max
+ return 0
}
proc askvhighlight {row id} {
set canvxmax [$canv cget -width]
catch {unset colormap}
catch {unset rowtextx}
+ setcanvscroll
}
proc setcanvscroll {} {
global canv canv2 canv3 numcommits linespc canvxmax canvy0
+ global lastscrollset lastscrollrows
set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
$canv conf -scrollregion [list 0 0 $canvxmax $ymax]
$canv2 conf -scrollregion [list 0 0 0 $ymax]
$canv3 conf -scrollregion [list 0 0 0 $ymax]
+ set lastscrollset [clock clicks -milliseconds]
+ set lastscrollrows $numcommits
}
proc visiblerows {} {
proc layoutmore {} {
global commitidx viewcomplete curview
global numcommits pending_select selectedline curview
- global lastscrollset commitinterest
-
- set canshow $commitidx($curview)
- if {$canshow <= $numcommits && !$viewcomplete($curview)} return
- if {$numcommits == 0} {
- allcanvs delete all
- }
- set r0 $numcommits
- set prev $numcommits
- set numcommits $canshow
- set t [clock clicks -milliseconds]
- if {$prev < 100 || $viewcomplete($curview) || $t - $lastscrollset > 500} {
- set lastscrollset $t
+ global lastscrollset lastscrollrows commitinterest
+
+ if {$lastscrollrows < 100 || $viewcomplete($curview) ||
+ [clock clicks -milliseconds] - $lastscrollset > 500} {
setcanvscroll
}
- set rows [visiblerows]
- set r1 [lindex $rows 1]
- if {$r1 >= $canshow} {
- set r1 [expr {$canshow - 1}]
- }
- if {$r0 <= $r1} {
- drawcommits $r0 $r1
- }
if {[info exists pending_select] &&
[commitinview $pending_select $curview]} {
selectline [rowofcommit $pending_select] 1
}
+ drawvisible
}
proc doshowlocalchanges {} {
# spawn off a process to do git diff-index --cached HEAD
proc dodiffindex {} {
global lserial showlocalchanges
+ global isworktree
- if {!$showlocalchanges} return
+ if {!$showlocalchanges || !$isworktree} return
incr lserial
set fd [open "|git diff-index --cached HEAD" r]
fconfigure $fd -blocking 0
if {[info exists selectedline] &&
$row <= $selectedline && $selectedline <= $endrow} {
set targetrow $selectedline
- } else {
+ } elseif {[info exists targetid]} {
set targetrow [expr {int(($row + $endrow) / 2)}]
}
- if {$targetrow >= $numcommits} {
- set targetrow [expr {$numcommits - 1}]
+ if {[info exists targetrow]} {
+ if {$targetrow >= $numcommits} {
+ set targetrow [expr {$numcommits - 1}]
+ }
+ set targetid [commitonrow $targetrow]
}
- set targetid [commitonrow $targetrow]
drawcommits $row $endrow
}
global commentend idtags linknum
global mergemax numcommits pending_select
global cmitmode showneartags allcommits
- global targetrow targetid
+ global targetrow targetid lastscrollrows
+ global autoselect
catch {unset pending_select}
$canv delete hover
unsel_reflist
stopfinding
if {$l < 0 || $l >= $numcommits} return
+ set id [commitonrow $l]
+ set targetid $id
+ set targetrow $l
+ set selectedline $l
+ set currentid $id
+ if {$lastscrollrows < $numcommits} {
+ setcanvscroll
+ }
+
set y [expr {$canvy0 + $l * $linespc}]
set ymax [lindex [$canv cget -scrollregion] 3]
set ytop [expr {$y - $linespc - 1}]
make_secsel $l
- set id [commitonrow $l]
if {$isnew} {
addtohistory [list selbyid $id]
}
- set selectedline $l
- set currentid $id
- set targetid $id
- set targetrow $l
$sha1entry delete 0 end
$sha1entry insert 0 $id
- $sha1entry selection from 0
- $sha1entry selection to end
+ if {$autoselect} {
+ $sha1entry selection from 0
+ $sha1entry selection to end
+ }
rhighlight_sel $id
$ctext conf -state normal
clear_ctext
set linknum 0
+ if {![info exists commitinfo($id)]} {
+ getcommit $id
+ }
set info $commitinfo($id)
set date [formatdate [lindex $info 2]]
$ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
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]
+ set line [string range $line 0 [expr {$i-1}]]
+ if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
+ set sha1 [lindex $line 2]
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
global diffids
global parents
global diffcontext
- global limitdiffs viewfiles curview
+ global limitdiffs vfilelimit curview
set diffmergeid $id
set diffids $id
# this doesn't seem to actually affect anything...
set cmd [concat | git diff-tree --no-commit-id --cc -U$diffcontext $id]
- if {$limitdiffs && $viewfiles($curview) ne {}} {
- set cmd [concat $cmd -- $viewfiles($curview)]
+ if {$limitdiffs && $vfilelimit($curview) ne {}} {
+ set cmd [concat $cmd -- $vfilelimit($curview)]
}
if {[catch {set mdf [open $cmd r]} err]} {
error_popup "[mc "Error getting merge diffs:"] $err"
proc gettreediffline {gdtf ids} {
global treediff treediffs treepending diffids diffmergeid
- global cmitmode viewfiles curview limitdiffs
+ global cmitmode vfilelimit curview limitdiffs
set nr 0
while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
return [expr {$nr >= 1000? 2: 1}]
}
close $gdtf
- if {$limitdiffs && $viewfiles($curview) ne {}} {
+ if {$limitdiffs && $vfilelimit($curview) ne {}} {
set flist {}
foreach f $treediff {
- if {[path_filter $viewfiles($curview) $f]} {
+ if {[path_filter $vfilelimit($curview) $f]} {
lappend flist $f
}
}
global diffinhdr treediffs
global diffcontext
global ignorespace
- global limitdiffs viewfiles curview
+ global limitdiffs vfilelimit curview
set cmd [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"]
if {$ignorespace} {
append cmd " -w"
}
- if {$limitdiffs && $viewfiles($curview) ne {}} {
- set cmd [concat $cmd -- $viewfiles($curview)]
+ if {$limitdiffs && $vfilelimit($curview) ne {}} {
+ set cmd [concat $cmd -- $vfilelimit($curview)]
}
if {[catch {set bdf [open $cmd r]} err]} {
puts "error getting diffs: $err"
$ctext tag conf d1 -elide [lindex $diffelide 1]
}
+proc highlightfile {loc cline} {
+ global ctext cflist cflist_top
+
+ $ctext yview $loc
+ $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
+ $cflist tag add highlight $cline.0 "$cline.0 lineend"
+ $cflist see $cline.0
+ set cflist_top $cline
+}
+
proc prevfile {} {
- global difffilestart ctext
- set prev [lindex $difffilestart 0]
+ global difffilestart ctext cmitmode
+
+ if {$cmitmode eq "tree"} return
+ set prev 0.0
+ set prevline 1
set here [$ctext index @0,0]
foreach loc $difffilestart {
if {[$ctext compare $loc >= $here]} {
- $ctext yview $prev
+ highlightfile $prev $prevline
return
}
set prev $loc
+ incr prevline
}
- $ctext yview $prev
+ highlightfile $prev $prevline
}
proc nextfile {} {
- global difffilestart ctext
+ global difffilestart ctext cmitmode
+
+ if {$cmitmode eq "tree"} return
set here [$ctext index @0,0]
+ set line 1
foreach loc $difffilestart {
+ incr line
if {[$ctext compare $loc > $here]} {
- $ctext yview $loc
+ highlightfile $loc $line
return
}
}
proc scrolltext {f0 f1} {
global searchstring
- .bleft.sb set $f0 $f1
+ .bleft.bottom.sb set $f0 $f1
if {$searchstring ne {}} {
searchmarkvisible 0
}
}
if {$id ne $nullid && $id ne $nullid2} {
set menu $rowctxmenu
- $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead]
+ if {$mainhead ne {}} {
+ $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead]
+ } else {
+ $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
+ }
} else {
set menu $fakerowmenu
}
}
proc cherrypick {} {
- global rowmenuid curview viewincl
+ global rowmenuid curview
global mainhead mainheadid
set oldhead [exec git rev-parse HEAD]
movedhead $newhead $mainhead
set mainheadid $newhead
}
- # remove oldhead from viewincl and add newhead
- set i [lsearch -exact $viewincl($curview) $oldhead]
- if {$i >= 0} {
- set viewincl($curview) [lreplace $viewincl($curview) $i $i]
- }
- lappend viewincl($curview) $newhead
redrawtags $oldhead
redrawtags $newhead
selbyid $newhead
proc doquit {} {
global stopped
+ global gitktmpdir
+
set stopped 100
savestuff .
destroy .
+
+ if {[info exists gitktmpdir]} {
+ catch {file delete -force $gitktmpdir}
+ }
}
proc mkfontdisp {font top which} {
global maxwidth maxgraphpct
global oldprefs prefstop showneartags showlocalchanges
global bgcolor fgcolor ctext diffcolors selectbgcolor
- global tabstop limitdiffs
+ global tabstop limitdiffs autoselect extdifftool
set top .gitkprefs
set prefstop $top
checkbutton $top.showlocal.b -variable showlocalchanges
pack $top.showlocal.b $top.showlocal.l -side left
grid x $top.showlocal -sticky w
+ frame $top.autoselect
+ label $top.autoselect.l -text [mc "Auto-select SHA1"] -font optionfont
+ checkbutton $top.autoselect.b -variable autoselect
+ pack $top.autoselect.b $top.autoselect.l -side left
+ grid x $top.autoselect -sticky w
label $top.ddisp -text [mc "Diff display options"]
grid $top.ddisp - -sticky w -pady 10
pack $top.ldiff.b $top.ldiff.l -side left
grid x $top.ldiff -sticky w
+ entry $top.extdifft -textvariable extdifftool
+ frame $top.extdifff
+ label $top.extdifff.l -text [mc "External diff tool" ] -font optionfont \
+ -padx 10
+ button $top.extdifff.b -text [mc "Choose..."] -font optionfont \
+ -command choose_extdiff
+ pack $top.extdifff.l $top.extdifff.b -side left
+ grid x $top.extdifff $top.extdifft -sticky w
+
label $top.cdisp -text [mc "Colors: press to choose"]
grid $top.cdisp - -sticky w -pady 10
label $top.bg -padx 40 -relief sunk -background $bgcolor
button $top.bgbut -text [mc "Background"] -font optionfont \
- -command [list choosecolor bgcolor 0 $top.bg background setbg]
+ -command [list choosecolor bgcolor {} $top.bg background setbg]
grid x $top.bgbut $top.bg -sticky w
label $top.fg -padx 40 -relief sunk -background $fgcolor
button $top.fgbut -text [mc "Foreground"] -font optionfont \
- -command [list choosecolor fgcolor 0 $top.fg foreground setfg]
+ -command [list choosecolor fgcolor {} $top.fg foreground setfg]
grid x $top.fgbut $top.fg -sticky w
label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
button $top.diffoldbut -text [mc "Diff: old lines"] -font optionfont \
grid x $top.hunksepbut $top.hunksep -sticky w
label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
button $top.selbgbut -text [mc "Select bg"] -font optionfont \
- -command [list choosecolor selectbgcolor 0 $top.selbgsep background setselbg]
+ -command [list choosecolor selectbgcolor {} $top.selbgsep background setselbg]
grid x $top.selbgbut $top.selbgsep -sticky w
label $top.cfont -text [mc "Fonts: press to choose"]
bind $top <Visibility> "focus $top.buts.ok"
}
+proc choose_extdiff {} {
+ global extdifftool
+
+ set prog [tk_getOpenFile -title "External diff tool" -multiple false]
+ if {$prog ne {}} {
+ set extdifftool $prog
+ }
+}
+
proc choosecolor {v vi w x cmd} {
global $v
}
# defaults...
-set datemode 0
set wrcomcmd "git diff-tree --stdin -p --pretty"
set gitencoding {}
set showlocalchanges 1
set limitdiffs 1
set datetimeformat "%Y-%m-%d %H:%M:%S"
+set autoselect 1
+
+set extdifftool "meld"
set colors {green red blue magenta darkgrey brown orange}
set bgcolor white
exit 1
}
-set mergeonly 0
set revtreeargs {}
set cmdline_files {}
set i 0
+set revtreeargscmd {}
foreach arg $argv {
- switch -- $arg {
+ switch -glob -- $arg {
"" { }
- "-d" { set datemode 1 }
- "--merge" {
- set mergeonly 1
- lappend revtreeargs $arg
- }
"--" {
set cmdline_files [lrange $argv [expr {$i + 1}] end]
break
}
+ "--argscmd=*" {
+ set revtreeargscmd [string range $arg 10 end]
+ }
default {
lappend revtreeargs $arg
}
}
if {$i >= [llength $argv] && $revtreeargs ne {}} {
- # no -- on command line, but some arguments (other than -d)
+ # no -- on command line, but some arguments (other than --argscmd)
if {[catch {
set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
set cmdline_files [split $f "\n"]
}
}
-if {$mergeonly} {
- # find the list of unmerged files
- set mlist {}
- set nr_unmerged 0
- if {[catch {
- set fd [open "| git ls-files -u" r]
- } err]} {
- show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
- exit 1
- }
- while {[gets $fd line] >= 0} {
- set i [string first "\t" $line]
- if {$i < 0} continue
- set fname [string range $line [expr {$i+1}] end]
- if {[lsearch -exact $mlist $fname] >= 0} continue
- incr nr_unmerged
- if {$cmdline_files eq {} || [path_filter $cmdline_files $fname]} {
- lappend mlist $fname
- }
- }
- catch {close $fd}
- if {$mlist eq {}} {
- if {$nr_unmerged == 0} {
- show_error {} . [mc "No files selected: --merge specified but\
- no files are unmerged."]
- } else {
- show_error {} . [mc "No files selected: --merge specified but\
- no unmerged files are within file limit."]
- }
- exit 1
- }
- set cmdline_files $mlist
-}
-
set nullid "0000000000000000000000000000000000000000"
set nullid2 "0000000000000000000000000000000000000001"
+set nullfile "/dev/null"
set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
set viewfiles(0) {}
set viewperm(0) 0
set viewargs(0) {}
+set viewargscmd(0) {}
set loginstance 0
set cmdlineok 0
set stuffsaved 0
set patchnum 0
set lserial 0
+set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
setcoords
makewindow
# wait for the window to become visible
wm title . "[file tail $argv0]: [file tail [pwd]]"
readrefs
-if {$cmdline_files ne {} || $revtreeargs ne {}} {
+if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
# create a view for the files/dirs specified on the command line
set curview 1
set selectedview 1
set viewname(1) [mc "Command line"]
set viewfiles(1) $cmdline_files
set viewargs(1) $revtreeargs
+ set viewargscmd(1) $revtreeargscmd
set viewperm(1) 0
+ set vdatemode(1) 0
addviewmenu 1
.bar.view entryconf [mc "Edit view..."] -state normal
.bar.view entryconf [mc "Delete view"] -state normal
set viewname($n) [lindex $v 0]
set viewfiles($n) [lindex $v 1]
set viewargs($n) [lindex $v 2]
+ set viewargscmd($n) [lindex $v 3]
set viewperm($n) 1
addviewmenu $n
}