From: Shawn O. Pearce Date: Mon, 9 Jul 2007 06:47:33 +0000 (-0400) Subject: git-gui: Perform our own magic shbang detection on Windows X-Git-Tag: v1.5.3-rc1~16^2~8 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=c136f2b8b9eaac7a702799de25648b74ef12618a;p=git.git git-gui: Perform our own magic shbang detection on Windows If we cannot locate a .exe for a git tool that we want to run than it may just be a Bourne shell script as these are popular in Git. In such a case the first line of the file will say "#!/bin/sh" so a UNIX kernel knows what program to start to parse and run that. But Windows doesn't support shbang lines, and neither does the Tcl that comes with Cygwin. We can pass control off to the git wrapper as that is a real Cygwin program and can therefore start the Bourne shell script, but that is at least two fork+exec calls to get the program running. One to do the fork+exec of the git wrapper and another to start the Bourne shell script. If the program is run multiple times it is rather expensive as the magic shbang detection won't be cached across executions. On MinGW/MSYS we don't have the luxury of such magic detection. The MSYS team has taught some of this magic to the git wrapper, but again its slower than it needs to be as the git wrapper must still go and run the Bourne shell after it is called. We now attempt to guess the shbang line on Windows by reading the first line of the file and building our own command line path from it. Currently we support Bourne shell (sh), Perl and Python. That is the entire set of shbang lines that appear in git.git today. Signed-off-by: Shawn O. Pearce --- diff --git a/git-gui.sh b/git-gui.sh index a3ac5daf1..7e6952c2b 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -302,19 +302,31 @@ proc _git_cmd {name} { set p [gitexec git-$name$::_search_exe] if {[file exists $p]} { set v [list $p] - } elseif {[is_Cygwin]} { - # On Cygwin git is a proper Cygwin program and knows - # how to properly restart the Cygwin environment and - # spawn its non-.exe support program. + } elseif {[is_Windows] && [file exists [gitexec git-$name]]} { + # Try to determine what sort of magic will make + # git-$name go and do its thing, because native + # Tcl on Windows doesn't know it. # - set v [list $::_git $name] - } elseif {[is_Windows] - && $::_sh ne {} - && [file exists [gitexec git-$name]]} { - # Assume this is a UNIX shell script. We can - # probably execute it through a Bourne shell. - # - set v [list $::_sh [gitexec git-$name]] + set p [gitexec git-$name] + set f [open $p r] + set s [gets $f] + close $f + + switch -glob -- $s { + #!*sh { set i sh } + #!*perl { set i perl } + #!*python { set i python } + default { error "git-$name is not supported: $s" } + } + + upvar #0 _$i interp + if {![info exists interp]} { + set interp [_which $i] + } + if {$interp eq {}} { + error "git-$name requires $i (not in PATH)" + } + set v [list $interp $p] } else { # Assume it is builtin to git somehow and we # aren't actually able to see a file for it. @@ -506,7 +518,6 @@ if {$_git eq {}} { exit 1 } set _nice [_which nice] -set _sh [_which sh] ###################################################################### ##