Skip to content

Commit 66a85a7

Browse files
HeyItsGilbertclaude
andcommitted
fix: support extensionless file targets; use trailing separator for containers
Copilot review identified that the extension-only heuristic broke extensionless file targets common on macOS/Linux (e.g. /usr/local/bin/terraform). New branching logic: - Trailing separator on Target => always a container (captured before GetUnresolvedProviderPathFromPSPath normalizes it away) - No trailing separator + (has extension OR parent already exists) => file target - Otherwise => container (created on Install) This restores backward-compatible handling of extensionless file paths while preserving the trailing-slash escape hatch for callers who want an extensionless container target. Update tests to use trailing slashes where container semantics are intended. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 997f26e commit 66a85a7

2 files changed

Lines changed: 22 additions & 7 deletions

File tree

PSDepend/PSDependScripts/FileDownload.ps1

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ Write-Verbose "Using URL: $URL"
7777
# Act on target path....
7878
$ToInstall = $False # Anti pattern
7979

80+
# Capture trailing-separator intent before GetUnresolvedProviderPathFromPSPath normalizes it away;
81+
# a trailing separator is an explicit signal that the target is a container, not a file.
82+
$endsWithSeparator = $Target -and
83+
$Target[-1] -in @([IO.Path]::DirectorySeparatorChar, [IO.Path]::AltDirectorySeparatorChar)
84+
8085
# Resolve PSDrive paths (e.g. TestDrive:) and relative paths to absolute filesystem paths
8186
$Target = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($Target)
8287

@@ -92,8 +97,15 @@ if (Test-Path $Target -PathType Leaf) {
9297
}
9398
$PathToAdd = Split-Path $Target -Parent
9499
}
95-
elseif ([IO.Path]::GetExtension($Target) -and -not (Test-Path $Target -PathType Container)) {
96-
# Target has a file extension — treat as a full destination file path
100+
elseif (
101+
-not $endsWithSeparator -and
102+
-not (Test-Path $Target -PathType Container) -and
103+
([IO.Path]::GetExtension($Target) -or (Test-Path $TargetParent))
104+
) {
105+
# Treat as a full destination file path.
106+
# Triggered when: has a file extension, OR parent already exists and caller gave no trailing separator.
107+
# The trailing-separator check preserves extensionless binary targets (e.g. /usr/local/bin/terraform)
108+
# while still allowing directory-like targets to be signalled with a trailing slash.
97109
$PathToAdd = $TargetParent
98110
if (-not (Test-Path $TargetParent)) {
99111
Write-Error "Could not find parent path [$TargetParent] for target [$Target]"
@@ -104,10 +116,10 @@ elseif ([IO.Path]::GetExtension($Target) -and -not (Test-Path $Target -PathType
104116
}
105117
$Path = $Target
106118
$ToInstall = $True
107-
Write-Verbose "Target has extension, treating as file path [$Target]"
119+
Write-Verbose "Treating as destination file path [$Target]"
108120
}
109121
else {
110-
# No extension (or already a container) — treat target as a directory
122+
# No extension (or already a container, or explicit trailing separator) — treat target as a directory
111123
Write-Verbose "[$Target] is a container, creating path to file"
112124
if (-not (Test-Path $Target) -and $PSDependAction -contains 'Install') {
113125
New-Item -ItemType Directory -Path $Target -Force | Out-Null

Tests/FileDownload.Type.Tests.ps1

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,10 @@ Describe 'FileDownload script' -Skip:$SkipUnsupported {
7373
}
7474

7575
It 'Creates a new directory and downloads into it when Target has no extension and does not exist' {
76-
$newDir = Join-Path (New-Item 'TestDrive:/dl5base' -ItemType Directory -Force).FullName 'newcontainer'
77-
$dep = New-PSDependFixture -DependencyName 'https://example.com/sample.dll' -DependencyType 'FileDownload' -Target $newDir
76+
$base = (New-Item 'TestDrive:/dl5base' -ItemType Directory -Force).FullName
77+
$newDir = Join-Path $base 'newcontainer'
78+
# Trailing separator signals "this is a container, not an extensionless file"
79+
$dep = New-PSDependFixture -DependencyName 'https://example.com/sample.dll' -DependencyType 'FileDownload' -Target "$newDir/"
7880
InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath; T = $newDir } {
7981
& $ScriptPath -Dependency $Dep
8082
}
@@ -100,7 +102,8 @@ Describe 'FileDownload script' -Skip:$SkipUnsupported {
100102
$baseDir = (New-Item 'TestDrive:/relbase' -ItemType Directory -Force).FullName
101103
Push-Location $baseDir
102104
try {
103-
$dep = New-PSDependFixture -DependencyName 'https://example.com/sample.dll' -DependencyType 'FileDownload' -Target 'subdir'
105+
# Trailing separator signals "this is a container, not an extensionless file"
106+
$dep = New-PSDependFixture -DependencyName 'https://example.com/sample.dll' -DependencyType 'FileDownload' -Target 'subdir/'
104107
InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } {
105108
& $ScriptPath -Dependency $Dep
106109
}

0 commit comments

Comments
 (0)