mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-18 18:09:28 +00:00
fix(mcp): don't hand git the server's stdin in _git_head (#4440)
graph_stats asks git for HEAD to report staleness. The child inherited the MCP stdio pipe, and on Windows git blocks on it: the call sat on the 3s timeout, or hung under Claude Code. prs.py already isolates stdin (#3318); these two _git_head copies were missed.
This commit is contained in:
1 parent
e8eb76e797
commit
7092f980ed
3 files changed
+25
-2
No files matched your search
+2
-1
@@ -226,7 +226,8 @@ def _git_head(cwd: "str | Path | None" = None) -> str | None:
|
||||
import subprocess as _sp
|
||||
try:
|
||||
r = _sp.run(
|
||||
["git", "rev-parse", "HEAD"], capture_output=True, text=True, timeout=3,
|
||||
["git", "rev-parse", "HEAD"], stdin=_sp.DEVNULL,
|
||||
capture_output=True, text=True, timeout=3,
|
||||
cwd=str(cwd) if cwd is not None else None,
|
||||
)
|
||||
return r.stdout.strip() if r.returncode == 0 else None
|
||||
|
||||
+2
-1
@@ -376,7 +376,8 @@ def _git_head(cwd: Path | str | None = None) -> str | None:
|
||||
import subprocess as _sp
|
||||
try:
|
||||
r = _sp.run(
|
||||
["git", "rev-parse", "HEAD"], capture_output=True, text=True, timeout=3,
|
||||
["git", "rev-parse", "HEAD"], stdin=_sp.DEVNULL,
|
||||
capture_output=True, text=True, timeout=3,
|
||||
cwd=str(cwd) if cwd is not None else None,
|
||||
)
|
||||
return r.stdout.strip() if r.returncode == 0 else None
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
"""_git_head must not hand git the caller's stdin (#4440).
|
||||
|
||||
Under an MCP stdio host, stdin is the protocol pipe. On Windows a git child that
|
||||
inherits it blocks, so `graph_stats` stalls on the timeout or hangs. Same class
|
||||
as the prs.py isolation in #3318.
|
||||
"""
|
||||
import subprocess
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from graphify import export, watch
|
||||
|
||||
|
||||
@pytest.mark.parametrize("module", [export, watch], ids=["export", "watch"])
|
||||
def test_git_head_passes_devnull_stdin(module, tmp_path):
|
||||
completed = MagicMock(returncode=0, stdout="abc123\n", stderr="")
|
||||
with patch("subprocess.run", return_value=completed) as mock_run:
|
||||
assert module._git_head(tmp_path) == "abc123"
|
||||
_args, kwargs = mock_run.call_args
|
||||
assert kwargs.get("stdin") == subprocess.DEVNULL
|
||||
Reference in new issue
Block a user