3
3
# This module is part of GitPython and is released under the
4
4
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
5
5
6
- import enum
7
6
from io import BytesIO
8
7
import logging
9
8
import os
14
13
import tempfile
15
14
16
15
import pytest
16
+ from sumtypes import constructor , sumtype
17
17
18
18
from git import (
19
19
IndexFile ,
39
39
log = logging .getLogger (__name__ )
40
40
41
41
42
- @enum . unique
43
- class _WinBashStatus ( enum . Enum ) :
42
+ @sumtype
43
+ class _WinBashStatus :
44
44
"""Status of bash.exe for native Windows. Affects which commit hook tests can pass.
45
45
46
46
Call :meth:`check` to check the status.
47
47
"""
48
48
49
- INAPPLICABLE = enum . auto ()
49
+ Inapplicable = constructor ()
50
50
"""This system is not native Windows: either not Windows at all, or Cygwin."""
51
51
52
- ABSENT = enum . auto ()
52
+ Absent = constructor ()
53
53
"""No command for ``bash.exe`` is found on the system."""
54
54
55
- NATIVE = enum . auto ()
55
+ Native = constructor ()
56
56
"""Running ``bash.exe`` operates outside any WSL distribution (as with Git Bash)."""
57
57
58
- WSL = enum . auto ()
58
+ Wsl = constructor ()
59
59
"""Running ``bash.exe`` calls ``bash`` in a WSL distribution."""
60
60
61
- WSL_NO_DISTRO = enum . auto ()
61
+ WslNoDistro = constructor ()
62
62
"""Running ``bash.exe` tries to run bash on a WSL distribution, but none exists."""
63
63
64
- ERROR_WHILE_CHECKING = enum . auto ( )
64
+ ErrorWhileChecking = constructor ( "error_or_process" )
65
65
"""Could not determine the status.
66
66
67
67
This should not trigger a skip or xfail, as it typically indicates either a fixable
68
68
problem on the test machine, such as an "Insufficient system resources exist to
69
69
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.
71
70
"""
72
71
73
72
@classmethod
@@ -93,7 +92,13 @@ def check(cls):
93
92
administrators occasionally put executables there in lieu of extending ``PATH``.
94
93
"""
95
94
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 )
97
102
98
103
try :
99
104
# Output rather than forwarding the test command's exit status so that if a
@@ -103,30 +108,21 @@ def check(cls):
103
108
command = ["bash.exe" , "-c" , script ]
104
109
proc = subprocess .run (command , capture_output = True , check = True , text = True )
105
110
except FileNotFoundError :
106
- return cls .ABSENT
111
+ return cls .Absent ()
107
112
except OSError as error :
108
- return cls . _error (error )
113
+ return error_running_bash (error )
109
114
except subprocess .CalledProcessError as error :
110
- no_distro_message = "Windows Subsystem for Linux has no installed distributions."
111
115
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 )
114
118
115
119
status = proc .stdout .rstrip ()
116
120
if status == "0" :
117
- return cls .WSL
121
+ return cls .Wsl ()
118
122
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 )
130
126
131
127
132
128
_win_bash_status = _WinBashStatus .check ()
@@ -1001,7 +997,7 @@ class Mocked:
1001
997
self .assertEqual (rel , os .path .relpath (path , root ))
1002
998
1003
999
@pytest .mark .xfail (
1004
- _win_bash_status is _WinBashStatus .WSL_NO_DISTRO ,
1000
+ type ( _win_bash_status ) is _WinBashStatus .WslNoDistro ,
1005
1001
reason = "Currently uses the bash.exe for WSL even with no WSL distro installed" ,
1006
1002
raises = HookExecutionError ,
1007
1003
)
@@ -1012,7 +1008,7 @@ def test_pre_commit_hook_success(self, rw_repo):
1012
1008
index .commit ("This should not fail" )
1013
1009
1014
1010
@pytest .mark .xfail (
1015
- _win_bash_status is _WinBashStatus .WSL_NO_DISTRO ,
1011
+ type ( _win_bash_status ) is _WinBashStatus .WslNoDistro ,
1016
1012
reason = "Currently uses the bash.exe for WSL even with no WSL distro installed" ,
1017
1013
raises = AssertionError ,
1018
1014
)
@@ -1023,7 +1019,7 @@ def test_pre_commit_hook_fail(self, rw_repo):
1023
1019
try :
1024
1020
index .commit ("This should fail" )
1025
1021
except HookExecutionError as err :
1026
- if _win_bash_status is _WinBashStatus .ABSENT :
1022
+ if type ( _win_bash_status ) is _WinBashStatus .Absent :
1027
1023
self .assertIsInstance (err .status , OSError )
1028
1024
self .assertEqual (err .command , [hp ])
1029
1025
self .assertEqual (err .stdout , "" )
@@ -1039,12 +1035,12 @@ def test_pre_commit_hook_fail(self, rw_repo):
1039
1035
raise AssertionError ("Should have caught a HookExecutionError" )
1040
1036
1041
1037
@pytest .mark .xfail (
1042
- _win_bash_status in {_WinBashStatus .ABSENT , _WinBashStatus .WSL },
1038
+ type ( _win_bash_status ) in {_WinBashStatus .Absent , _WinBashStatus .Wsl },
1043
1039
reason = "Specifically seems to fail on WSL bash (in spite of #1399)" ,
1044
1040
raises = AssertionError ,
1045
1041
)
1046
1042
@pytest .mark .xfail (
1047
- _win_bash_status is _WinBashStatus .WSL_NO_DISTRO ,
1043
+ type ( _win_bash_status ) is _WinBashStatus .WslNoDistro ,
1048
1044
reason = "Currently uses the bash.exe for WSL even with no WSL distro installed" ,
1049
1045
raises = HookExecutionError ,
1050
1046
)
@@ -1062,7 +1058,7 @@ def test_commit_msg_hook_success(self, rw_repo):
1062
1058
self .assertEqual (new_commit .message , "{} {}" .format (commit_message , from_hook_message ))
1063
1059
1064
1060
@pytest .mark .xfail (
1065
- _win_bash_status is _WinBashStatus .WSL_NO_DISTRO ,
1061
+ type ( _win_bash_status ) is _WinBashStatus .WslNoDistro ,
1066
1062
reason = "Currently uses the bash.exe for WSL even with no WSL distro installed" ,
1067
1063
raises = AssertionError ,
1068
1064
)
@@ -1073,7 +1069,7 @@ def test_commit_msg_hook_fail(self, rw_repo):
1073
1069
try :
1074
1070
index .commit ("This should fail" )
1075
1071
except HookExecutionError as err :
1076
- if _win_bash_status is _WinBashStatus .ABSENT :
1072
+ if type ( _win_bash_status ) is _WinBashStatus .Absent :
1077
1073
self .assertIsInstance (err .status , OSError )
1078
1074
self .assertEqual (err .command , [hp ])
1079
1075
self .assertEqual (err .stdout , "" )
0 commit comments