Make _WinBashStatus instances carry all their info · gitpython-developers/GitPython@7ff3cee
@@ -3,7 +3,6 @@
33# This module is part of GitPython and is released under the
44# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
556-import enum
76from io import BytesIO
87import logging
98import os
@@ -14,6 +13,7 @@
1413import tempfile
15141615import pytest
16+from sumtypes import constructor, sumtype
17171818from git import (
1919IndexFile,
@@ -39,35 +39,34 @@
3939log = logging.getLogger(__name__)
4040414142-@enum.unique
43-class _WinBashStatus(enum.Enum):
42+@sumtype
43+class _WinBashStatus:
4444"""Status of bash.exe for native Windows. Affects which commit hook tests can pass.
45454646 Call :meth:`check` to check the status.
4747 """
484849-INAPPLICABLE = enum.auto()
49+Inapplicable = constructor()
5050"""This system is not native Windows: either not Windows at all, or Cygwin."""
515152-ABSENT = enum.auto()
52+Absent = constructor()
5353"""No command for ``bash.exe`` is found on the system."""
545455-NATIVE = enum.auto()
55+Native = constructor()
5656"""Running ``bash.exe`` operates outside any WSL distribution (as with Git Bash)."""
575758-WSL = enum.auto()
58+Wsl = constructor()
5959"""Running ``bash.exe`` calls ``bash`` in a WSL distribution."""
606061-WSL_NO_DISTRO = enum.auto()
61+WslNoDistro = constructor()
6262"""Running ``bash.exe` tries to run bash on a WSL distribution, but none exists."""
636364-ERROR_WHILE_CHECKING = enum.auto()
64+ErrorWhileChecking = constructor("error_or_process")
6565"""Could not determine the status.
66666767 This should not trigger a skip or xfail, as it typically indicates either a fixable
6868 problem on the test machine, such as an "Insufficient system resources exist to
6969 complete the requested service" error starting WSL, or a bug in this detection code.
70- ``ERROR_WHILE_CHECKING.error_or_process`` has details about the most recent failure.
7170 """
72717372@classmethod
@@ -93,7 +92,13 @@ def check(cls):
9392 administrators occasionally put executables there in lieu of extending ``PATH``.
9493 """
9594if os.name != "nt":
96-return cls.INAPPLICABLE
95+return cls.Inapplicable()
96+97+no_distro_message = "Windows Subsystem for Linux has no installed distributions."
98+99+def error_running_bash(error):
100+log.error("Error running bash.exe to check WSL status: %s", error)
101+return cls.ErrorWhileChecking(error)
9710298103try:
99104# Output rather than forwarding the test command's exit status so that if a
@@ -103,30 +108,21 @@ def check(cls):
103108command = ["bash.exe", "-c", script]
104109proc = subprocess.run(command, capture_output=True, check=True, text=True)
105110except FileNotFoundError:
106-return cls.ABSENT
111+return cls.Absent()
107112except OSError as error:
108-return cls._error(error)
113+return error_running_bash(error)
109114except subprocess.CalledProcessError as error:
110-no_distro_message = "Windows Subsystem for Linux has no installed distributions."
111115if error.returncode == 1 and error.stdout.startswith(no_distro_message):
112-return cls.WSL_NO_DISTRO
113-return cls._error(error)
116+return cls.WslNoDistro()
117+return error_running_bash(error)
114118115119status = proc.stdout.rstrip()
116120if status == "0":
117-return cls.WSL
121+return cls.Wsl()
118122if status == "1":
119-return cls.NATIVE
120-return cls._error(proc)
121-122-@classmethod
123-def _error(cls, error_or_process):
124-if isinstance(error_or_process, subprocess.CompletedProcess):
125-log.error("Strange output checking WSL status: %s", error_or_process.stdout)
126-else:
127-log.error("Error running bash.exe to check WSL status: %s", error_or_process)
128-cls.ERROR_WHILE_CHECKING.error_or_process = error_or_process
129-return cls.ERROR_WHILE_CHECKING
123+return cls.Native()
124+log.error("Strange output checking WSL status: %s", proc.stdout)
125+return cls.ErrorWhileChecking(proc)
130126131127132128_win_bash_status = _WinBashStatus.check()
@@ -1001,7 +997,7 @@ class Mocked:
1001997self.assertEqual(rel, os.path.relpath(path, root))
10029981003999@pytest.mark.xfail(
1004- _win_bash_status is _WinBashStatus.WSL_NO_DISTRO,
1000+ type(_win_bash_status) is _WinBashStatus.WslNoDistro,
10051001 reason="Currently uses the bash.exe for WSL even with no WSL distro installed",
10061002 raises=HookExecutionError,
10071003 )
@@ -1012,7 +1008,7 @@ def test_pre_commit_hook_success(self, rw_repo):
10121008index.commit("This should not fail")
1013100910141010@pytest.mark.xfail(
1015- _win_bash_status is _WinBashStatus.WSL_NO_DISTRO,
1011+ type(_win_bash_status) is _WinBashStatus.WslNoDistro,
10161012 reason="Currently uses the bash.exe for WSL even with no WSL distro installed",
10171013 raises=AssertionError,
10181014 )
@@ -1023,7 +1019,7 @@ def test_pre_commit_hook_fail(self, rw_repo):
10231019try:
10241020index.commit("This should fail")
10251021except HookExecutionError as err:
1026-if _win_bash_status is _WinBashStatus.ABSENT:
1022+if type(_win_bash_status) is _WinBashStatus.Absent:
10271023self.assertIsInstance(err.status, OSError)
10281024self.assertEqual(err.command, [hp])
10291025self.assertEqual(err.stdout, "")
@@ -1039,12 +1035,12 @@ def test_pre_commit_hook_fail(self, rw_repo):
10391035raise AssertionError("Should have caught a HookExecutionError")
1040103610411037@pytest.mark.xfail(
1042- _win_bash_status in {_WinBashStatus.ABSENT, _WinBashStatus.WSL},
1038+ type(_win_bash_status) in {_WinBashStatus.Absent, _WinBashStatus.Wsl},
10431039 reason="Specifically seems to fail on WSL bash (in spite of #1399)",
10441040 raises=AssertionError,
10451041 )
10461042@pytest.mark.xfail(
1047- _win_bash_status is _WinBashStatus.WSL_NO_DISTRO,
1043+ type(_win_bash_status) is _WinBashStatus.WslNoDistro,
10481044 reason="Currently uses the bash.exe for WSL even with no WSL distro installed",
10491045 raises=HookExecutionError,
10501046 )
@@ -1062,7 +1058,7 @@ def test_commit_msg_hook_success(self, rw_repo):
10621058self.assertEqual(new_commit.message, "{} {}".format(commit_message, from_hook_message))
1063105910641060@pytest.mark.xfail(
1065- _win_bash_status is _WinBashStatus.WSL_NO_DISTRO,
1061+ type(_win_bash_status) is _WinBashStatus.WslNoDistro,
10661062 reason="Currently uses the bash.exe for WSL even with no WSL distro installed",
10671063 raises=AssertionError,
10681064 )
@@ -1073,7 +1069,7 @@ def test_commit_msg_hook_fail(self, rw_repo):
10731069try:
10741070index.commit("This should fail")
10751071except HookExecutionError as err:
1076-if _win_bash_status is _WinBashStatus.ABSENT:
1072+if type(_win_bash_status) is _WinBashStatus.Absent:
10771073self.assertIsInstance(err.status, OSError)
10781074self.assertEqual(err.command, [hp])
10791075self.assertEqual(err.stdout, "")