Skip to content

Commit

Permalink
Ensure the full path to git is used on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
sdispater committed Sep 17, 2021
1 parent 17a712e commit ce7df69
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
43 changes: 41 additions & 2 deletions poetry/core/vcs/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from typing import Any
from typing import Optional

from poetry.core.utils._compat import WINDOWS


pattern_formats = {
"protocol": r"\w+",
Expand Down Expand Up @@ -183,13 +185,48 @@ def __str__(self) -> str:
GitUrl = namedtuple("GitUrl", ["url", "revision", "subdirectory"])


_executable: Optional[str] = None


def executable():
global _executable

if _executable is not None:
return _executable

if WINDOWS:
# Finding git via where.exe
where = "%WINDIR%\\System32\\where.exe"
paths = subprocess.check_output(
[where, "git"], shell=True, encoding="oem"
).split("\n")
for path in paths:
if not path:
continue

path = Path(path.strip())
try:
path.relative_to(Path.cwd())
except ValueError:
_executable = str(path)

break
else:
_executable = "git"

if _executable is None:
raise RuntimeError("Unable to find a valid git executable")

return _executable


class GitConfig:
def __init__(self, requires_git_presence: bool = False) -> None:
self._config = {}

try:
config_list = subprocess.check_output(
["git", "config", "-l"], stderr=subprocess.STDOUT
[executable(), "config", "-l"], stderr=subprocess.STDOUT
).decode()

m = re.findall("(?ms)^([^=]+)=(.*?)$", config_list)
Expand Down Expand Up @@ -344,7 +381,9 @@ def run(self, *args: Any, **kwargs: Any) -> str:
) + args

return (
subprocess.check_output(["git"] + list(args), stderr=subprocess.STDOUT)
subprocess.check_output(
[executable()] + list(args), stderr=subprocess.STDOUT
)
.decode()
.strip()
)
Expand Down
44 changes: 44 additions & 0 deletions tests/vcs/test_vcs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import subprocess

from pathlib import Path

import pytest

from poetry.core.utils._compat import WINDOWS
from poetry.core.vcs.git import Git
from poetry.core.vcs.git import GitError
from poetry.core.vcs.git import GitUrl
Expand Down Expand Up @@ -366,3 +369,44 @@ def test_git_checkout_raises_error_on_invalid_repository():
def test_git_rev_parse_raises_error_on_invalid_repository():
with pytest.raises(GitError):
Git().rev_parse("-u./payload")


@pytest.mark.skipif(
not WINDOWS,
reason="Retrieving the complete path to git is only necessary on Windows, for security reasons",
)
def test_ensure_absolute_path_to_git(mocker):
def checkout_output(cmd, *args, **kwargs):
if Path(cmd[0]).name == "where.exe":
return "\n".join(
[
str(Path.cwd().joinpath("git.exe")),
"C:\\Git\\cmd\\git.exe",
]
)

return b""

mock = mocker.patch.object(subprocess, "check_output", side_effect=checkout_output)

Git().run("config")

assert mock.call_args_list[-1][0][0] == [
"C:\\Git\\cmd\\git.exe",
"config",
]


@pytest.mark.skipif(
not WINDOWS,
reason="Retrieving the complete path to git is only necessary on Windows, for security reasons",
)
def test_ensure_existing_git_executable_is_found(mocker):
mock = mocker.patch.object(subprocess, "check_output", return_value=b"")

Git().run("config")

cmd = Path(mock.call_args_list[-1][0][0][0])

assert cmd.is_absolute()
assert cmd.name == "git.exe"

0 comments on commit ce7df69

Please sign in to comment.