33# This module is part of GitPython and is released under the
44# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
55
6- import enum
76from io import BytesIO
87import logging
98import os
1413import tempfile
1514
1615import pytest
16+ from sumtypes import constructor , sumtype
1717
1818from git import (
1919 IndexFile ,
3939log = logging .getLogger (__name__ )
4040
4141
42- @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.
4545
4646 Call :meth:`check` to check the status.
4747 """
4848
49- INAPPLICABLE = enum . auto ()
49+ Inapplicable = constructor ()
5050 """This system is not native Windows: either not Windows at all, or Cygwin."""
5151
52- ABSENT = enum . auto ()
52+ Absent = constructor ()
5353 """No command for ``bash.exe`` is found on the system."""
5454
55- NATIVE = enum . auto ()
55+ Native = constructor ()
5656 """Running ``bash.exe`` operates outside any WSL distribution (as with Git Bash)."""
5757
58- WSL = enum . auto ()
58+ Wsl = constructor ()
5959 """Running ``bash.exe`` calls ``bash`` in a WSL distribution."""
6060
61- WSL_NO_DISTRO = enum . auto ()
61+ WslNoDistro = constructor ()
6262 """Running ``bash.exe` tries to run bash on a WSL distribution, but none exists."""
6363
64- ERROR_WHILE_CHECKING = enum . auto ( )
64+ ErrorWhileChecking = constructor ( "error_or_process" )
6565 """Could not determine the status.
6666
6767 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 """
7271
7372 @classmethod
@@ -93,7 +92,13 @@ def check(cls):
9392 administrators occasionally put executables there in lieu of extending ``PATH``.
9493 """
9594 if 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 )
97102
98103 try :
99104 # Output rather than forwarding the test command's exit status so that if a
@@ -103,30 +108,21 @@ def check(cls):
103108 command = ["bash.exe" , "-c" , script ]
104109 proc = subprocess .run (command , capture_output = True , check = True , text = True )
105110 except FileNotFoundError :
106- return cls .ABSENT
111+ return cls .Absent ()
107112 except OSError as error :
108- return cls . _error (error )
113+ return error_running_bash (error )
109114 except subprocess .CalledProcessError as error :
110- no_distro_message = "Windows Subsystem for Linux has no installed distributions."
111115 if 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 )
114118
115119 status = proc .stdout .rstrip ()
116120 if status == "0" :
117- return cls .WSL
121+ return cls .Wsl ()
118122 if 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 )
130126
131127
132128_win_bash_status = _WinBashStatus .check ()
@@ -1001,7 +997,7 @@ class Mocked:
1001997 self .assertEqual (rel , os .path .relpath (path , root ))
1002998
1003999 @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):
10121008 index .commit ("This should not fail" )
10131009
10141010 @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):
10231019 try :
10241020 index .commit ("This should fail" )
10251021 except HookExecutionError as err :
1026- if _win_bash_status is _WinBashStatus .ABSENT :
1022+ if type ( _win_bash_status ) is _WinBashStatus .Absent :
10271023 self .assertIsInstance (err .status , OSError )
10281024 self .assertEqual (err .command , [hp ])
10291025 self .assertEqual (err .stdout , "" )
@@ -1039,12 +1035,12 @@ def test_pre_commit_hook_fail(self, rw_repo):
10391035 raise AssertionError ("Should have caught a HookExecutionError" )
10401036
10411037 @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):
10621058 self .assertEqual (new_commit .message , "{} {}" .format (commit_message , from_hook_message ))
10631059
10641060 @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):
10731069 try :
10741070 index .commit ("This should fail" )
10751071 except HookExecutionError as err :
1076- if _win_bash_status is _WinBashStatus .ABSENT :
1072+ if type ( _win_bash_status ) is _WinBashStatus .Absent :
10771073 self .assertIsInstance (err .status , OSError )
10781074 self .assertEqual (err .command , [hp ])
10791075 self .assertEqual (err .stdout , "" )
0 commit comments