From 598d192f118480c2f2294daaaabfff9afbc95b6c Mon Sep 17 00:00:00 2001 From: argszero Date: Fri, 23 Oct 2026 06:44:41 +0800 Subject: [PATCH] emrg: a guard pins the locale it asserts in, instead of reading the host's --- tests/test_check_merge_order.py | 13 ++++++++++++- tests/test_check_merge_plan_suite.py | 8 ++++++++ tests/test_check_merge_sequence.py | 9 +++++++++ tests/test_merge_tree.py | 11 ++++++++++- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/tests/test_check_merge_order.py b/tests/test_check_merge_order.py index 9a2b03884..75bac92bd 100644 --- a/tests/test_check_merge_order.py +++ b/tests/test_check_merge_order.py @@ -836,7 +836,7 @@ def test_the_shapes_git_really_prints(self, tmp_path) -> None: assert re.fullmatch(r"[0-9a-f]{40}", conflict.stdout.splitlines()[0]) assert any("\tf.txt" in line for line in conflict.stdout.splitlines()) - def test_the_probe_answers_the_way_real_git_does(self, tmp_path) -> None: + def test_the_probe_answers_the_way_real_git_does(self, tmp_path, monkeypatch) -> None: """The arm that would have caught a substring reading, on a real process. The arms above carry a stderr this file writes, which is why they could not @@ -849,7 +849,18 @@ def test_the_probe_answers_the_way_real_git_does(self, tmp_path) -> None: This is also the arm that fails when git's diagnostic changes shape - if the usage block stops arriving with the error line, the premise the probe's rule rests on is gone and the row says so instead of quietly passing. + + That premise is a *shape*, so the locale is pinned rather than the assertion + loosened: git translates the usage block's header and its option + descriptions, and measured 2026-10-23 on a host with + `LC_MESSAGES=zh_CN.UTF-8` the same block arrives as + `用法:git merge-tree [--write-tree] ...`. Without the pin this row measures + the host's language rather than git's behaviour, and it fails on a tree that + is fine. `monkeypatch` reverts the environment when the test ends, so the pin + reaches the git subprocesses this arm starts and nothing else in the suite. """ + monkeypatch.setenv("LC_ALL", "C") + monkeypatch.setenv("LANG", "C") repo = tmp_path / "r" repo.mkdir() self._git(repo, "init", "-q", "-b", "main") diff --git a/tests/test_check_merge_plan_suite.py b/tests/test_check_merge_plan_suite.py index f193a392a..065bd13b9 100644 --- a/tests/test_check_merge_plan_suite.py +++ b/tests/test_check_merge_plan_suite.py @@ -1309,7 +1309,15 @@ def test_the_shapes_git_really_prints(self, tmp_path, mod, monkeypatch) -> None: A tab in the name makes the stage block quote it *and* makes the prose below the block tab-separated, which is the whole defect: measured here on real git, with the old reading run over the same bytes as a control arm. + + git translates its own messages, so the prose assertion below is a host + dependency unless the locale is pinned: measured 2026-10-23 on a host with + `LC_MESSAGES=zh_CN.UTF-8`, git answered `自动合并 ftab.txt` while the + paths the product reads came back the same either way. Pinned, so the subject + stays the *shape* git prints rather than the host's language. """ + monkeypatch.setenv("LC_ALL", "C") + monkeypatch.setenv("LANG", "C") repo = tmp_path / "tab-conflict" tab_name = "f\ttab.txt" _two_branch_conflict_on(repo, tab_name) diff --git a/tests/test_check_merge_sequence.py b/tests/test_check_merge_sequence.py index 224dbdc24..af8eca7db 100644 --- a/tests/test_check_merge_sequence.py +++ b/tests/test_check_merge_sequence.py @@ -1542,7 +1542,16 @@ def test_a_blob_input_is_not_a_conflicting_step(mod, tmp_path, monkeypatch): that evidence (and can end in the refusal that says every open PR conflicts), and the paths named there come from a report that was never read. Real git, so the shape is measured rather than described. + + git translates its own messages, so the assertion on its sentence below is a host + dependency unless the locale is pinned: measured 2026-10-23 on a host with + `LC_MESSAGES=zh_CN.UTF-8`, git answered `不是可以合并的东西` and this arm failed on a + tree that is fine. `_run` inherits this process's environment, so pinning it here + reaches the subprocess the product starts, and `monkeypatch` puts it back when the + test ends. """ + monkeypatch.setenv("LC_ALL", "C") + monkeypatch.setenv("LANG", "C") repo = tmp_path / "blob" repo.mkdir() _git(mod, repo, "init", "-q", "-b", "master") diff --git a/tests/test_merge_tree.py b/tests/test_merge_tree.py index b04254adf..b6d03f7b6 100644 --- a/tests/test_merge_tree.py +++ b/tests/test_merge_tree.py @@ -346,7 +346,7 @@ def run(argv, cwd=None): mod.merged_tree_sha(a, b, run=run) def test_a_depth_one_clone_turns_one_merge_into_unrelated_histories( - self, mod, tmp_path + self, mod, tmp_path, monkeypatch ) -> None: """The same two commits, two answers, one variable: the clone's boundary. @@ -360,7 +360,16 @@ def test_a_depth_one_clone_turns_one_merge_into_unrelated_histories( The clone is a repository this test creates and cuts itself, so nothing outside `tmp_path` is read or written. + + git translates its own messages, so the diagnosis assertion below is a host + dependency unless the locale is pinned: measured 2026-10-23 on a host with + `LC_MESSAGES=zh_CN.UTF-8`, git answered `拒绝合并无关的历史` and this arm failed + on a tree that is fine - the product's own diagnosis was still right and still + named the repair. The shallowness is this test's own fixture (it cuts a depth-1 + clone); the checkout it runs in need not be shallow, and is not. """ + monkeypatch.setenv("LC_ALL", "C") + monkeypatch.setenv("LANG", "C") repo, a, b = self._conflict_on(tmp_path, "plain.txt") clone = tmp_path / "shallow" self._git(