Skip to content

Commit fadfb7a

Browse files
saygoxLee-W
authored andcommitted
feat(commands/commit): apply prepare-commit-msg hook for Mac
1 parent 13b8e2c commit fadfb7a

File tree

2 files changed

+69
-19
lines changed

2 files changed

+69
-19
lines changed

commitizen/commands/commit.py

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
import contextlib
44
import os
5+
import selectors
56
import shutil
67
import subprocess
78
import sys
89
import tempfile
10+
from asyncio import DefaultEventLoopPolicy, get_event_loop_policy, set_event_loop_policy
11+
from io import IOBase
912

1013
import questionary
1114

@@ -27,14 +30,31 @@
2730
from commitizen.git import smart_open
2831

2932

30-
class WrapStdin:
31-
def __init__(self):
32-
fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
33-
tty = open(fd, "wb+", buffering=0)
33+
class CZEventLoopPolicy(DefaultEventLoopPolicy):
34+
def get_event_loop(self):
35+
self.set_event_loop(self._loop_factory(selectors.SelectSelector()))
36+
return self._local._loop
37+
38+
39+
class WrapStdx:
40+
def __init__(self, stdx: IOBase):
41+
self._fileno = stdx.fileno()
42+
if sys.platform == "linux":
43+
if self._fileno == 0:
44+
fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
45+
tty = open(fd, "wb+", buffering=0)
46+
else:
47+
tty = open("/dev/tty", "w")
48+
else:
49+
fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
50+
if self._fileno == 0:
51+
tty = open(fd, "wb+", buffering=0)
52+
else:
53+
tty = open(fd, "rb+", buffering=0)
3454
self.tty = tty
3555

3656
def __getattr__(self, key):
37-
if key == "encoding":
57+
if key == "encoding" and (sys.platform != "linux" or self._fileno == 0):
3858
return "UTF-8"
3959
return getattr(self.tty, key)
4060

@@ -126,9 +146,11 @@ def __call__(self):
126146
old_stdin = sys.stdin
127147
old_stdout = sys.stdout
128148
old_stderr = sys.stderr
129-
sys.stdin = WrapStdin()
130-
sys.stdout = open("/dev/tty", "w")
131-
sys.stderr = open("/dev/tty", "w")
149+
old_event_loop_policy = get_event_loop_policy()
150+
set_event_loop_policy(CZEventLoopPolicy())
151+
sys.stdin = WrapStdx(sys.stdin)
152+
sys.stdout = WrapStdx(sys.stdout)
153+
sys.stderr = WrapStdx(sys.stderr)
132154

133155
if git.is_staging_clean() and not (dry_run or allow_empty):
134156
raise NothingToCommitError("No files added to staging!")
@@ -151,9 +173,17 @@ def __call__(self):
151173
else:
152174
m = self.prompt_commit_questions()
153175

176+
if commit_msg_file:
177+
sys.stdin.close()
178+
sys.stdout.close()
179+
sys.stderr.close()
180+
set_event_loop_policy(old_event_loop_policy)
181+
sys.stdin = old_stdin
182+
sys.stdout = old_stdout
183+
sys.stderr = old_stderr
184+
154185
if manual_edit:
155186
m = self.manual_edit(m)
156-
157187
out.info(f"\n{m}\n")
158188

159189
if write_message_to_file:
@@ -164,12 +194,6 @@ def __call__(self):
164194
raise DryRunExit()
165195

166196
if commit_msg_file:
167-
sys.stdin.close()
168-
sys.stdout.close()
169-
sys.stderr.close()
170-
sys.stdin = old_stdin
171-
sys.stdout = old_stdout
172-
sys.stderr = old_stderr
173197
defaultmesaage = ""
174198
with open(commit_msg_file) as f:
175199
defaultmesaage = f.read()

tests/commands/test_commit_command.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,8 @@ def test_commit_from_pre_commit_msg_hook(config, mocker, capsys):
542542
}
543543

544544
commit_mock = mocker.patch("commitizen.git.commit")
545-
mocker.patch("commitizen.commands.commit.WrapStdin")
545+
commit_mock.return_value = cmd.Command("success", "", "", "", 0)
546+
mocker.patch("commitizen.commands.commit.WrapStdx")
546547
mocker.patch("os.open")
547548
reader_mock = mocker.mock_open(read_data="\n\n#test\n")
548549
mocker.patch("builtins.open", reader_mock, create=True)
@@ -553,13 +554,38 @@ def test_commit_from_pre_commit_msg_hook(config, mocker, capsys):
553554
assert "Commit message is successful!" in out
554555
commit_mock.assert_not_called()
555556

556-
557-
def test_WrapStdin(mocker):
557+
def test_WrapStdx(mocker):
558558
mocker.patch("os.open")
559559
reader_mock = mocker.mock_open(read_data="data")
560560
mocker.patch("builtins.open", reader_mock, create=True)
561561

562-
wrap_stdin = commands.commit.WrapStdin()
562+
stdin_mock_fileno=mocker.patch.object(sys.stdin, 'fileno')
563+
stdin_mock_fileno.return_value = 0
564+
wrap_stdin = commands.commit.WrapStdx(sys.stdin)
563565

564566
assert wrap_stdin.encoding == "UTF-8"
565567
assert wrap_stdin.read() == "data"
568+
569+
570+
writer_mock = mocker.mock_open(read_data="data")
571+
mocker.patch("builtins.open", writer_mock, create=True)
572+
stdout_mock_fileno=mocker.patch.object(sys.stdout, 'fileno')
573+
stdout_mock_fileno.return_value = 1
574+
wrap_stout = commands.commit.WrapStdx(sys.stdout)
575+
wrap_stout.write("data")
576+
577+
writer_mock.assert_called_once_with("/dev/tty", 'w')
578+
writer_mock().write.assert_called_once_with("data")
579+
580+
581+
writer_mock = mocker.mock_open(read_data="data")
582+
mocker.patch("builtins.open", writer_mock, create=True)
583+
stderr_mock_fileno=mocker.patch.object(sys.stdout, 'fileno')
584+
stderr_mock_fileno.return_value = 2
585+
wrap_sterr = commands.commit.WrapStdx(sys.stderr)
586+
587+
588+
wrap_sterr.write("data")
589+
590+
writer_mock.assert_called_once_with("/dev/tty", 'w')
591+
writer_mock().write.assert_called_once_with("data")

0 commit comments

Comments
 (0)