Skip to content

Commit d6d544f

Browse files
committed
cmd: on windows, we will now fallback to using git.cmd, as the default installation puts it into the path, instead of git.exe. Of course we warn about the performance penalty that goes with it. Fortunately, using a wrapped git.exe works when creating pipes to the process, admittedly I was a bit surprised by this.
fixes #26
1 parent 0e9eef4 commit d6d544f

File tree

1 file changed

+39
-6
lines changed

1 file changed

+39
-6
lines changed

Diff for: git/cmd.py

+39-6
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,15 @@ class Git(LazyMixin):
4848
# The size in bytes read from stdout when copying git's output to another stream
4949
max_chunk_size = 1024*64
5050

51+
git_exec_name = "git" # default that should work on linux and windows
52+
git_exec_name_win = "git.cmd" # alternate command name, windows only
53+
5154
# Enables debugging of GitPython's git commands
5255
GIT_PYTHON_TRACE = os.environ.get("GIT_PYTHON_TRACE", False)
5356

5457
# Provide the full path to the git executable. Otherwise it assumes git is in the path
55-
GIT_PYTHON_GIT_EXECUTABLE = os.environ.get("GIT_PYTHON_GIT_EXECUTABLE", 'git')
58+
_git_exec_env_var = "GIT_PYTHON_GIT_EXECUTABLE"
59+
GIT_PYTHON_GIT_EXECUTABLE = os.environ.get(_git_exec_env_var, git_exec_name)
5660

5761

5862
class AutoInterrupt(object):
@@ -449,11 +453,40 @@ def _call_process(self, method, *args, **kwargs):
449453

450454
ext_args = self.__unpack_args([a for a in args if a is not None])
451455
args = opt_args + ext_args
452-
453-
call = [self.GIT_PYTHON_GIT_EXECUTABLE, dashify(method)]
454-
call.extend(args)
455-
456-
return self.execute(call, **_kwargs)
456+
457+
def make_call():
458+
call = [self.GIT_PYTHON_GIT_EXECUTABLE, dashify(method)]
459+
call.extend(args)
460+
return call
461+
#END utility to recreate call after changes
462+
463+
if sys.platform == 'win32':
464+
try:
465+
try:
466+
return self.execute(make_call(), **_kwargs)
467+
except WindowsError:
468+
# did we switch to git.cmd already, or was it changed from default ? permanently fail
469+
if self.GIT_PYTHON_GIT_EXECUTABLE != self.git_exec_name:
470+
raise
471+
#END handle overridden variable
472+
type(self).GIT_PYTHON_GIT_EXECUTABLE = self.git_exec_name_win
473+
call = [self.GIT_PYTHON_GIT_EXECUTABLE] + list(args)
474+
475+
try:
476+
return self.execute(make_call(), **_kwargs)
477+
finally:
478+
import warnings
479+
msg = "WARNING: Automatically switched to use git.cmd as git executable, which reduces performance by ~70%."
480+
msg += "Its recommended to put git.exe into the PATH or to set the %s environment variable to the executable's location" % self._git_exec_env_var
481+
warnings.warn(msg)
482+
#END print of warning
483+
#END catch first failure
484+
except WindowsError:
485+
raise WindowsError("The system cannot find or execute the file at %r" % self.GIT_PYTHON_GIT_EXECUTABLE)
486+
#END provide better error message
487+
else:
488+
return self.execute(make_call(), **_kwargs)
489+
#END handle windows default installation
457490

458491
def _parse_object_header(self, header_line):
459492
"""

0 commit comments

Comments
 (0)