From 42c041a71e44bd29f997bd123109a4e1f46d345a Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 25 Apr 2019 11:58:20 -0400 Subject: [PATCH 1/4] fixup! gitk: fix another invocation with an overly long command-line This was an ugly hack, and in preparation for fixing it the right way, we revert this hack. Signed-off-by: Johannes Schindelin --- gitk-git/gitk | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/gitk-git/gitk b/gitk-git/gitk index d1d77d832ee0ed..953db03496a931 100755 --- a/gitk-git/gitk +++ b/gitk-git/gitk @@ -406,7 +406,7 @@ proc start_rev_list {view} { if {$revs eq {}} { return 0 } - set args [limit_arg_length [concat $vflags($view) $revs]] + set args [concat $vflags($view) $revs] } else { set args $vorigargs($view) } @@ -10177,7 +10177,18 @@ proc getallcommits {} { } } if {$ids ne {}} { - set cmd [limit_arg_length [concat $cmd $ids]] + set cmd [concat $cmd $ids] + # The maximum command line length for the CreateProcess function is 32767 characters, see + # http://blogs.msdn.com/oldnewthing/archive/2003/12/10/56028.aspx + # Be a little conservative in case Tcl adds some more stuff to the command line we do not + # know about and truncate the command line at a SHA1-boundary below 32000 characters. + if {[tk windowingsystem] == "win32" && + [string length $cmd] > 32000} { + set ndx [string last " " $cmd 32000] + if {$ndx != -1} { + set cmd [string range $cmd 0 $ndx] + } + } set fd [open $cmd r] fconfigure $fd -blocking 0 incr allcommits @@ -10188,21 +10199,6 @@ proc getallcommits {} { } } -# The maximum command line length for the CreateProcess function is 32767 characters, see -# http://blogs.msdn.com/oldnewthing/archive/2003/12/10/56028.aspx -# Be a little conservative in case Tcl adds some more stuff to the command line we do not -# know about and truncate the command line at a SHA1-boundary below 32000 characters. -proc limit_arg_length {cmd} { - if {[tk windowingsystem] == "win32" && - [string length $cmd] > 32000} { - set ndx [string last " " $cmd 32000] - if {$ndx != -1} { - return [string range $cmd 0 $ndx] - } - } - return $cmd -} - # Since most commits have 1 parent and 1 child, we group strings of # such commits into "arcs" joining branch/merge points (BMPs), which # are commits that either don't have 1 parent or don't have 1 child. From 2372d65dd9a1d1f3786d458a3ef7f8f164ee2d08 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 25 Apr 2019 12:00:37 -0400 Subject: [PATCH 2/4] fixup! gitk: work around the command line limit on Windows This was an ugly hack, and in preparation for fixing it the right way, we revert this hack. Signed-off-by: Johannes Schindelin --- gitk-git/gitk | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/gitk-git/gitk b/gitk-git/gitk index 953db03496a931..a50519a24234e4 100755 --- a/gitk-git/gitk +++ b/gitk-git/gitk @@ -10177,19 +10177,7 @@ proc getallcommits {} { } } if {$ids ne {}} { - set cmd [concat $cmd $ids] - # The maximum command line length for the CreateProcess function is 32767 characters, see - # http://blogs.msdn.com/oldnewthing/archive/2003/12/10/56028.aspx - # Be a little conservative in case Tcl adds some more stuff to the command line we do not - # know about and truncate the command line at a SHA1-boundary below 32000 characters. - if {[tk windowingsystem] == "win32" && - [string length $cmd] > 32000} { - set ndx [string last " " $cmd 32000] - if {$ndx != -1} { - set cmd [string range $cmd 0 $ndx] - } - } - set fd [open $cmd r] + set fd [open [concat $cmd $ids] r] fconfigure $fd -blocking 0 incr allcommits nowbusy allcommits From d91b8550365a37cdfc004ab9d45c12217735cc00 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 25 Apr 2019 12:05:29 -0400 Subject: [PATCH 3/4] gitk: prevent overly long command lines To avoid running into command line limitations, some of Git's commands support the `--stdin` option. Let's use exactly this option in the three rev-list/log invocations in gitk that would otherwise possibly run the danger of trying to invoke a too-long command line. While it is easy to redirect either stdin or stdout in Tcl/Tk scripts, what we need here is both. We need to capture the output, yet we also need to pipe in the revs/files arguments via stdin (because stdin does not have any limit, unlike the command line). To help this, we use the neat Tcl feature where you can capture stdout and at the same time feed a fixed string as stdin to the spawned process. One non-obvious aspect about this change is that the `--stdin` option allows to specify revs, the double-dash, and files, but *no* other options such as `--not`. This is addressed by prefixing the "negative" revs with `^` explicitly rather than relying on the `--not` option (thanks for coming up with that idea, Max!). This fixes https://github.com/git-for-windows/git/issues/1987 Analysis-and-initial-patch-by: Max Kirillov Signed-off-by: Johannes Schindelin --- gitk-git/gitk | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/gitk-git/gitk b/gitk-git/gitk index a50519a24234e4..01ee363207cadb 100755 --- a/gitk-git/gitk +++ b/gitk-git/gitk @@ -406,14 +406,16 @@ proc start_rev_list {view} { if {$revs eq {}} { return 0 } - set args [concat $vflags($view) $revs] + set args $vflags($view) } else { + set revs {} set args $vorigargs($view) } if {[catch { set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \ - --parents --boundary $args "--" $files] r] + --parents --boundary $args --stdin \ + "<<[join [concat $revs "--" $files] "\\n"]"] r] } err]} { error_popup "[mc "Error executing git log:"] $err" return 0 @@ -555,13 +557,19 @@ proc updatecommits {} { set revs $newrevs set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]] } - set args [concat $vflags($view) $revs --not $oldpos] + set args $vflags($view) + foreach r $oldpos { + lappend revs "^$r" + } } else { + set revs {} set args $vorigargs($view) } if {[catch { set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \ - --parents --boundary $args "--" $vfilelimit($view)] r] + --parents --boundary $args --stdin \ + "<<[join [concat $revs "--" \ + $vfilelimit($view)] "\\n"]" r] } err]} { error_popup "[mc "Error executing git log:"] $err" return @@ -10174,10 +10182,16 @@ proc getallcommits {} { foreach id $seeds { lappend ids "^$id" } + lappend ids "--" } } if {$ids ne {}} { - set fd [open [concat $cmd $ids] r] + if {$ids eq "--all"} { + set cmd [concat $cmd "--all"] + } else { + set cmd [concat $cmd --stdin "<<[join $ids "\\n"]"] + } + set fd [open $cmd r] fconfigure $fd -blocking 0 incr allcommits nowbusy allcommits From b62ef9ceea871df65680a2f6d7076e6a36ff0980 Mon Sep 17 00:00:00 2001 From: "Max A.K" Date: Fri, 26 Apr 2019 07:38:22 -0400 Subject: [PATCH 4/4] fixup! gitk: prevent overly long command lines This adds a missing closing bracket. Co-Authored-By: Johannes Schindelin Signed-off-by: Max A.K --- gitk-git/gitk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitk-git/gitk b/gitk-git/gitk index 01ee363207cadb..4542c63d01af2e 100755 --- a/gitk-git/gitk +++ b/gitk-git/gitk @@ -569,7 +569,7 @@ proc updatecommits {} { set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \ --parents --boundary $args --stdin \ "<<[join [concat $revs "--" \ - $vfilelimit($view)] "\\n"]" r] + $vfilelimit($view)] "\\n"]"] r] } err]} { error_popup "[mc "Error executing git log:"] $err" return