| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 09ac0a1 commit 6991a2a
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,7 +4,7 @@ | |||
| 4 | 4 | # This module is part of GitPython and is released under | |
| 5 | 5 | # the BSD License: http://www.opensource.org/licenses/bsd-license.php | |
| 6 | 6 | ||
| 7 | - from contextlib import contextmanager | ||
| 7 | + import contextlib | ||
| 8 | 8 | import io | |
| 9 | 9 | import logging | |
| 10 | 10 | import os | |
@@ -19,6 +19,7 @@ | |||
| 19 | 19 | import threading | |
| 20 | 20 | from collections import OrderedDict | |
| 21 | 21 | from textwrap import dedent | |
| 22 | + import unittest.mock | ||
| 22 | 23 | ||
| 23 | 24 | from git.compat import ( | |
| 24 | 25 | string_types, | |
@@ -705,11 +706,15 @@ def execute(self, command, | |||
| 705 | 706 | cmd_not_found_exception = OSError | |
| 706 | 707 | if kill_after_timeout: | |
| 707 | 708 | raise GitCommandError(command, '"kill_after_timeout" feature is not supported on Windows.') | |
| 709 | + | ||
| 710 | + # Only search PATH, not CWD. This must be in the *caller* environment. The "1" can be any value. | ||
| 711 | + patch_caller_env = unittest.mock.patch.dict(os.environ, {"NoDefaultCurrentDirectoryInExePath": "1"}) | ||
| 708 | 712 | else: | |
| 709 | 713 | if sys.version_info[0] > 2: | |
| 710 | 714 | cmd_not_found_exception = FileNotFoundError # NOQA # exists, flake8 unknown @UndefinedVariable | |
| 711 | 715 | else: | |
| 712 | 716 | cmd_not_found_exception = OSError | |
| 717 | + patch_caller_env = contextlib.nullcontext() | ||
| 713 | 718 | # end handle | |
| 714 | 719 | ||
| 715 | 720 | stdout_sink = (PIPE | |
@@ -721,19 +726,21 @@ def execute(self, command, | |||
| 721 | 726 | log.debug("Popen(%s, cwd=%s, universal_newlines=%s, shell=%s, istream=%s)", | |
| 722 | 727 | command, cwd, universal_newlines, shell, istream_ok) | |
| 723 | 728 | try: | |
| 724 | - proc = Popen(command, | ||
| 725 | - env=env, | ||
| 726 | - cwd=cwd, | ||
| 727 | - bufsize=-1, | ||
| 728 | - stdin=istream, | ||
| 729 | - stderr=PIPE, | ||
| 730 | - stdout=stdout_sink, | ||
| 731 | - shell=shell is not None and shell or self.USE_SHELL, | ||
| 732 | - close_fds=is_posix, # unsupported on windows | ||
| 733 | - universal_newlines=universal_newlines, | ||
| 734 | - creationflags=PROC_CREATIONFLAGS, | ||
| 735 | - **subprocess_kwargs | ||
| 736 | - ) | ||
| 729 | + with patch_caller_env: | ||
| 730 | + proc = Popen( | ||
| 731 | + command, | ||
| 732 | + env=env, | ||
| 733 | + cwd=cwd, | ||
| 734 | + bufsize=-1, | ||
| 735 | + stdin=istream, | ||
| 736 | + stderr=PIPE, | ||
| 737 | + stdout=stdout_sink, | ||
| 738 | + shell=shell is not None and shell or self.USE_SHELL, | ||
| 739 | + close_fds=is_posix, # unsupported on windows | ||
| 740 | + universal_newlines=universal_newlines, | ||
| 741 | + creationflags=PROC_CREATIONFLAGS, | ||
| 742 | + **subprocess_kwargs, | ||
| 743 | + ) | ||
| 737 | 744 | except cmd_not_found_exception as err: | |
| 738 | 745 | raise GitCommandNotFound(command, err) | |
| 739 | 746 | ||
@@ -862,7 +869,7 @@ def update_environment(self, **kwargs): | |||
| 862 | 869 | del self._environment[key] | |
| 863 | 870 | return old_env | |
| 864 | 871 | ||
| 865 | - @contextmanager | ||
| 872 | + @contextlib.contextmanager | ||
| 866 | 873 | def custom_environment(self, **kwargs): | |
| 867 | 874 | """ | |
| 868 | 875 | A context manager around the above ``update_environment`` method to restore the | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,10 +4,12 @@ | |||
| 4 | 4 | # | |
| 5 | 5 | # This module is part of GitPython and is released under | |
| 6 | 6 | # the BSD License: http://www.opensource.org/licenses/bsd-license.php | |
| 7 | + import contextlib | ||
| 7 | 8 | import os | |
| 9 | + import shutil | ||
| 8 | 10 | import subprocess | |
| 9 | 11 | import sys | |
| 10 | - from tempfile import TemporaryFile | ||
| 12 | + from tempfile import TemporaryDirectory, TemporaryFile | ||
| 11 | 13 | ||
| 12 | 14 | from git import ( | |
| 13 | 15 | Git, | |
@@ -40,6 +42,16 @@ | |||
| 40 | 42 | ||
| 41 | 43 | from git.compat import is_win | |
| 42 | 44 | ||
| 45 | + @contextlib.contextmanager | ||
| 46 | + def _chdir(new_dir): | ||
| 47 | + """Context manager to temporarily change directory. Not reentrant.""" | ||
| 48 | + old_dir = os.getcwd() | ||
| 49 | + os.chdir(new_dir) | ||
| 50 | + try: | ||
| 51 | + yield | ||
| 52 | + finally: | ||
| 53 | + os.chdir(old_dir) | ||
| 54 | + | ||
| 43 | 55 | ||
| 44 | 56 | class TestGit(TestBase): | |
| 45 | 57 | ||
@@ -100,6 +112,23 @@ def test_it_transforms_kwargs_into_git_command_arguments(self): | |||
| 100 | 112 | def test_it_executes_git_to_shell_and_returns_result(self): | |
| 101 | 113 | assert_match(r'^git version [\d\.]{2}.*$', self.git.execute(["git", "version"])) | |
| 102 | 114 | ||
| 115 | + def test_it_executes_git_not_from_cwd(self): | ||
| 116 | + with TemporaryDirectory() as tmpdir: | ||
| 117 | + if is_win: | ||
| 118 | + # Copy an actual binary executable that is not git. | ||
| 119 | + other_exe_path = os.path.join(os.getenv("WINDIR"), "system32", "hostname.exe") | ||
| 120 | + impostor_path = os.path.join(tmpdir, "git.exe") | ||
| 121 | + shutil.copy(other_exe_path, impostor_path) | ||
| 122 | + else: | ||
| 123 | + # Create a shell script that doesn't do anything. | ||
| 124 | + impostor_path = os.path.join(tmpdir, "git") | ||
| 125 | + with open(impostor_path, mode="w", encoding="utf-8") as file: | ||
| 126 | + print("#!/bin/sh", file=file) | ||
| 127 | + os.chmod(impostor_path, 0o755) | ||
| 128 | + | ||
| 129 | + with _chdir(tmpdir): | ||
| 130 | + self.assertRegex(self.git.execute(["git", "version"]), r"^git version\b") | ||
| 131 | + | ||
| 103 | 132 | def test_it_accepts_stdin(self): | |
| 104 | 133 | filename = fixture_path("cat_file_blob") | |
| 105 | 134 | with open(filename, 'r') as fh: | |
| Back | FazBrowse Home | New Git URL |
0 commit comments