Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions scripts/powershell/common.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ function Save-FeatureJson {
# Read current value and skip write when unchanged
if (Test-Path -LiteralPath $fjPath -PathType Leaf) {
try {
$raw = Get-Content -LiteralPath $fjPath -Raw
$raw = [System.IO.File]::ReadAllText($fjPath, [System.Text.Encoding]::UTF8)
$cfg = $raw | ConvertFrom-Json
if ($cfg.feature_directory -eq $FeatureDirectory) {
return
Expand Down Expand Up @@ -187,7 +187,7 @@ function Get-FeaturePathsEnv {
Save-FeatureJson -RepoRoot $repoRoot -FeatureDirectory $env:SPECIFY_FEATURE_DIRECTORY
}
} elseif (Test-Path $featureJson) {
$featureJsonRaw = Get-Content -LiteralPath $featureJson -Raw
$featureJsonRaw = [System.IO.File]::ReadAllText($featureJson, [System.Text.Encoding]::UTF8)
try {
$featureConfig = $featureJsonRaw | ConvertFrom-Json
} catch {
Expand Down
36 changes: 35 additions & 1 deletion tests/test_check_prerequisites_paths_only.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def _write_feature_json(
repo: Path, feature_directory: str = "specs/001-my-feature"
) -> None:
(repo / ".specify" / "feature.json").write_text(
json.dumps({"feature_directory": feature_directory}),
json.dumps({"feature_directory": feature_directory}, ensure_ascii=False),
encoding="utf-8",
)

Expand Down Expand Up @@ -288,6 +288,40 @@ def test_ps_paths_only_succeeds_on_non_spec_branch(prereq_repo: Path) -> None:
assert "FEATURE_DIR" in data


@pytest.mark.skipif(
not _WINDOWS_POWERSHELL, reason="Windows PowerShell 5.1 not available"
)
def test_windows_powershell_reads_bomless_utf8_feature_json(
prereq_repo: Path,
) -> None:
"""Windows PowerShell must decode non-ASCII feature paths as UTF-8 (#4333)."""
feature_directory = "specs/001-后台信息架构"
feature_path = prereq_repo / feature_directory
feature_path.mkdir(parents=True)
_write_feature_json(prereq_repo, feature_directory)

resolved_path = prereq_repo / "resolved-feature-path.txt"
common_ps = prereq_repo / ".specify" / "scripts" / "powershell" / "common.ps1"
ps_command = (
f". '{common_ps}'; "
"$resolved = Get-FeaturePathsEnv -NoPersist; "
"$utf8NoBom = New-Object System.Text.UTF8Encoding($false); "
f"[System.IO.File]::WriteAllText('{resolved_path}', "
"[string]$resolved.FEATURE_DIR, $utf8NoBom)"
)
result = subprocess.run(
[_WINDOWS_POWERSHELL, "-NoProfile", "-Command", ps_command],
cwd=prereq_repo,
capture_output=True,
text=True,
check=False,
env=_clean_env(),
)

assert result.returncode == 0, result.stderr
assert resolved_path.read_text(encoding="utf-8") == str(feature_path)


@pytest.mark.skipif(not (HAS_PWSH or _WINDOWS_POWERSHELL), reason="no PowerShell available")
@pytest.mark.parametrize(
("use_env_var", "specify_feature", "expected_branch"),
Expand Down