From c1683d0d9534a6a8256bd32785f45aa46ce32e1e Mon Sep 17 00:00:00 2001 From: Max Kirillov Date: Thu, 25 Apr 2019 00:31:45 +0300 Subject: [PATCH] gitk: prevent "file name too long" error at update gitk excludes all known references calling "git log" at "Update" (F5). At windows, when there are too many of them the command fails because of command line length limitation. Maybe with some bigger number of references it would also fail at other platforms. Fix by using --stdin to pass the known references and file filtering. From testing it looks like no additional waiting is required, it is enough to close both input and output pipe to finalize the child process. Signed-off-by: Max Kirillov --- gitk-git/gitk | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/gitk-git/gitk b/gitk-git/gitk index d1d77d832ee0ed..834b3a856801a7 100755 --- a/gitk-git/gitk +++ b/gitk-git/gitk @@ -500,6 +500,44 @@ proc getcommits {selid} { } } +proc updatecommits_command {args oldpos view} { + global have_tk86 show_notes vfilelimit + + set command_head [concat git log --no-color -z --pretty=raw $show_notes --parents --boundary $args] + + if {!$have_tk86} { + # "chan pipe" is added in tcl 8.6 + return [open [concat | $command_head --not $oldpos -- $vfilelimit($view)] r] + } else { + set pIn [chan pipe] + set pOut [chan pipe] + set child [exec sh -c [concat $command_head --stdin] <@ [lindex $pIn 0] >@ [lindex $pOut 1] &] + close [lindex $pIn 0] + close [lindex $pOut 1] + + foreach arg $oldpos { + if {![regexp {[0-9a-f]{16}} $arg]} { + puts "oops: unexpected refspec to ignore (only hashes are expected): $arg" + } + puts [lindex $pIn 1] "^$arg" + } + puts [lindex $pIn 1] "--" + foreach file_arg $vfilelimit($view) { + if {[string first "\n" $file_arg] > -1} { + # --stdin gets each line as argument, no quoting required + # this approach seems to miss newlines in file name + # which is unlikely + puts "oops: newlines in file names not supported" + } else { + puts [lindex $pIn 1] $file_arg + } + } + close [lindex $pIn 1] + + return [lindex $pOut 0] + } +} + proc updatecommits {} { global curview vcanopt vorigargs vfilelimit viewinstances global viewactive viewcomplete tclencoding @@ -507,7 +545,6 @@ proc updatecommits {} { global mainheadid viewmainheadid viewmainheadid_orig pending_select global hasworktree global varcid vposids vnegids vflags vrevs - global show_notes set hasworktree [hasworktree] rereadrefs @@ -555,13 +592,13 @@ proc updatecommits {} { set revs $newrevs set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]] } - set args [concat $vflags($view) $revs --not $oldpos] + set args [concat $vflags($view) $revs] } else { set args $vorigargs($view) + set oldpos {} } if {[catch { - set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \ - --parents --boundary $args "--" $vfilelimit($view)] r] + set fd [updatecommits_command $args $oldpos $view] } err]} { error_popup "[mc "Error executing git log:"] $err" return