Skip to content

Commit 80f4e7d

Browse files
jawwad-aliclaude
andcommitted
fix(scripts): count subdirectory-only dirs as non-empty in PowerShell
Test-DirHasFiles (the documented PowerShell twin of bash check_dir) tested non-emptiness with `Get-ChildItem | Where-Object { -not $_.PSIsContainer }`, counting only top-level FILES and ignoring subdirectories. Bash check_dir (`-n $(ls -A ...)`) and the PowerShell JSON-path contracts checks (check-prerequisites.ps1 / setup-tasks.ps1, no PSIsContainer filter) both count ANY entry. So a contracts/ directory whose only contents are subdirectories (e.g. contracts/v1/openapi.yaml) was reported present by bash, by bash JSON, and by PowerShell JSON, but [FAIL]/absent by PowerShell text mode — the lone outlier. Drop the PSIsContainer filter so Test-DirHasFiles counts any entry, matching the other three code paths. Add bash + PowerShell parity tests asserting a subdir-only contracts/ dir is reported non-empty in both shells. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent b6b74d4 commit 80f4e7d

2 files changed

Lines changed: 51 additions & 1 deletion

File tree

scripts/powershell/common.ps1

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,11 @@ function Test-FileExists {
209209

210210
function Test-DirHasFiles {
211211
param([string]$Path, [string]$Description)
212-
if ((Test-Path -Path $Path -PathType Container) -and (Get-ChildItem -Path $Path -ErrorAction SilentlyContinue | Where-Object { -not $_.PSIsContainer } | Select-Object -First 1)) {
212+
# A directory counts as non-empty when it contains ANY entry (files or
213+
# subdirectories), matching bash check_dir (`-n $(ls -A ...)`) and the JSON
214+
# contracts checks. Filtering out subdirectories would mis-report a dir whose
215+
# only contents are subdirectories (e.g. contracts/v1/openapi.yaml) as empty.
216+
if ((Test-Path -Path $Path -PathType Container) -and (Get-ChildItem -Path $Path -ErrorAction SilentlyContinue | Select-Object -First 1)) {
213217
Write-Output " [OK] $Description"
214218
return $true
215219
} else {

tests/test_setup_tasks.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,3 +840,49 @@ def test_setup_tasks_ps_errors_without_feature_context(
840840
output = result.stderr + result.stdout
841841
assert result.returncode != 0
842842
assert "Feature directory not found" in output
843+
844+
845+
# ---------------------------------------------------------------------------
846+
# Directory non-emptiness parity: a dir whose only contents are subdirectories
847+
# (e.g. contracts/v1/openapi.yaml) must count as non-empty in both shells.
848+
# ---------------------------------------------------------------------------
849+
850+
def _run_bash_check_dir(repo: Path, target: Path) -> subprocess.CompletedProcess:
851+
script = repo / ".specify" / "scripts" / "bash" / "common.sh"
852+
return subprocess.run(
853+
["bash", "-c", 'source "$1"; check_dir "$2" "contracts/"', "bash", str(script), str(target)],
854+
cwd=repo, capture_output=True, text=True, check=False, env=_clean_env(),
855+
)
856+
857+
858+
def _run_powershell_test_dir(repo: Path, target: Path) -> subprocess.CompletedProcess:
859+
script = repo / ".specify" / "scripts" / "powershell" / "common.ps1"
860+
exe = "pwsh" if HAS_PWSH else _WINDOWS_POWERSHELL
861+
return subprocess.run(
862+
[exe, "-NoProfile", "-Command",
863+
'& { param($common, $dir) . $common; Test-DirHasFiles -Path $dir -Description "contracts/" }',
864+
str(script), str(target)],
865+
cwd=repo, capture_output=True, text=True, check=False, env=_clean_env(),
866+
)
867+
868+
869+
@requires_bash
870+
def test_check_dir_bash_counts_subdir_only_contracts(tasks_repo: Path) -> None:
871+
"""bash check_dir treats a dir containing only subdirectories as non-empty."""
872+
contracts = tasks_repo / "contracts" / "v1"
873+
contracts.mkdir(parents=True)
874+
(contracts / "openapi.yaml").write_text("openapi: 3.0\n", encoding="utf-8")
875+
result = _run_bash_check_dir(tasks_repo, tasks_repo / "contracts")
876+
assert result.returncode == 0, result.stderr
877+
assert "✓" in result.stdout and "✗" not in result.stdout
878+
879+
880+
@pytest.mark.skipif(not (HAS_PWSH or _WINDOWS_POWERSHELL), reason="no PowerShell available")
881+
def test_test_dir_has_files_ps_counts_subdir_only_contracts(tasks_repo: Path) -> None:
882+
"""Test-DirHasFiles must match bash: a subdir-only dir counts as non-empty."""
883+
contracts = tasks_repo / "contracts" / "v1"
884+
contracts.mkdir(parents=True)
885+
(contracts / "openapi.yaml").write_text("openapi: 3.0\n", encoding="utf-8")
886+
result = _run_powershell_test_dir(tasks_repo, tasks_repo / "contracts")
887+
assert result.returncode == 0, result.stderr
888+
assert "[OK]" in result.stdout and "[FAIL]" not in result.stdout

0 commit comments

Comments
 (0)