fix(local): stop re-reading cwd marker file

This commit is contained in:
LeonSGP43 2026-07-12 08:28:21 -07:00 committed by Teknium
parent 9420ad946a
commit 0ccd05b78a
3 changed files with 28 additions and 41 deletions

View file

@ -160,13 +160,14 @@ class TestUpdateCwdRejectsMissingPaths:
with patch.object(LocalEnvironment, "init_session", autospec=True, return_value=None):
env = LocalEnvironment(cwd=str(original), timeout=10)
# Simulate the stale-marker case: the prior command's ``pwd -P`` left
# a path in the cwd file, but that path has since been deleted.
# Simulate the stale-marker case: the prior command emitted a cwd
# marker for a directory that has since been deleted.
deleted = tmp_path / "wedge-repro"
with open(env._cwd_file, "w") as f:
f.write(str(deleted))
marker = env._cwd_marker
env._update_cwd({"output": "", "returncode": 0})
env._update_cwd(
{"output": f"x\n{marker}{deleted}{marker}\n", "returncode": 0}
)
assert env.cwd == str(original)
@ -178,10 +179,10 @@ class TestUpdateCwdRejectsMissingPaths:
with patch.object(LocalEnvironment, "init_session", autospec=True, return_value=None):
env = LocalEnvironment(cwd=str(original), timeout=10)
marker = env._cwd_marker
with open(env._cwd_file, "w") as f:
f.write(str(new_dir))
env._update_cwd({"output": "", "returncode": 0})
env._update_cwd(
{"output": f"x\n{marker}{new_dir}{marker}\n", "returncode": 0}
)
assert env.cwd == str(new_dir)

View file

@ -180,15 +180,15 @@ class TestResolveSafeCwdWindows:
# ---------------------------------------------------------------------------
# End-to-end: _update_cwd via marker file (Windows simulation)
# End-to-end: _update_cwd via stdout marker (Windows simulation)
# ---------------------------------------------------------------------------
class TestUpdateCwdWindowsMsys:
def test_marker_file_msys_path_stored_in_native_form(
def test_marker_output_msys_path_stored_in_native_form(
self, monkeypatch, tmp_path,
):
"""When Git Bash writes ``/c/Users/x`` to the cwd marker file on
Windows, ``_update_cwd`` must translate to native form before
"""When Git Bash emits ``/c/Users/x`` in the cwd marker on Windows,
``_update_cwd`` must translate to native form before
validating and storing otherwise ``os.path.isdir`` rejects a
perfectly real directory."""
original = tmp_path / "starting"
@ -205,18 +205,21 @@ class TestUpdateCwdWindowsMsys:
# Pretend Git Bash wrote an MSYS path that maps to tmp_path/"next"
new_dir = tmp_path / "next"
new_dir.mkdir()
marker = env._cwd_marker
with open(env._cwd_file, "w") as f:
f.write("/c/whatever/from/bash")
# Translate the synthetic MSYS string to the real native dir.
# Translate the synthetic MSYS marker path to the real native dir.
def fake_translate(p):
if p == "/c/whatever/from/bash":
return str(new_dir)
return p
with patch.object(local_mod, "_msys_to_windows_path", side_effect=fake_translate):
env._update_cwd({"output": "", "returncode": 0})
env._update_cwd(
{
"output": f"x\n{marker}/c/whatever/from/bash{marker}\n",
"returncode": 0,
}
)
assert env.cwd == str(new_dir)

View file

@ -1353,31 +1353,14 @@ class LocalEnvironment(BaseEnvironment):
pass
def _update_cwd(self, result: dict):
"""Read CWD from temp file (local-only, no round-trip needed).
"""Update cwd from the stdout marker emitted by the wrapped command.
Skip the assignment when the path no longer exists as a directory
``pwd -P`` on a deleted cwd can leave a stale value in the marker
file, and propagating it would re-wedge the next ``Popen``. The
``_run_bash`` recovery path will resolve a safe fallback if needed.
On Windows, the value written by Git Bash's ``pwd -P`` is in
MSYS form (``/c/Users/x``). Translate it to native Windows form
before validating with ``os.path.isdir`` and before storing on
``self.cwd``; otherwise the isdir check rejects every valid
result and ``_run_bash`` later prints a misleading "cwd is
missing" warning on every command.
The base command wrapper already appends ``pwd -P`` to stdout inside a
session-specific marker, so the local backend can share the same parser
as remote backends instead of re-reading the temp file it just wrote.
``_extract_cwd_from_output`` keeps the local Windows normalization and
stale-path rollback semantics intact.
"""
try:
with open(self._cwd_file, encoding="utf-8") as f:
cwd_path = f.read().strip()
if _IS_WINDOWS:
cwd_path = _msys_to_windows_path(cwd_path)
if cwd_path and os.path.isdir(cwd_path):
self.cwd = cwd_path
except (OSError, FileNotFoundError):
pass
# Still strip the marker from output so it's not visible
self._extract_cwd_from_output(result)
def _extract_cwd_from_output(self, result: dict):