diff --git a/CHANGELOG.md b/CHANGELOG.md index 4904be8..fb6335f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,15 +9,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- `FileDownload` is now supported on all platforms (`windows`, `core`, `macos`, `linux`); there was no Windows-only code blocking this (#98). -- `FileDownload` relative `Target` paths are now rooted against `$PWD` before resolution, matching the intuitive expectation of callers (#49). +- `FileDownload` is now supported on all platforms (`windows`, `core`, + `macos`, `linux`); there was no Windows-only code blocking this (#98). +- `FileDownload` relative `Target` paths are now rooted against `$PWD` + before resolution, matching the intuitive expectation of callers (#49). ### Fixed - `Get-Dependency -InputObject` no longer mutates the caller's hashtable: `PSDependOptions` is now preserved after the call, so a second invocation with the same object still honors global options such as `Target` (#35). -- `FileDownload` no longer misidentifies a directory-like `Target` (no file extension, or trailing slash) as a full file path when its parent happens to exist; the handler now uses a file-extension heuristic to distinguish file targets from container targets and creates the directory when it does not yet exist (#49). +- `FileDownload` no longer misidentifies a directory-like `Target` (no + file extension, or trailing slash) as a full file path when its parent + happens to exist; the handler now uses a file-extension heuristic to + distinguish file targets from container targets and creates the directory + when it does not yet exist (#49). +- `Git` handler no longer silently ignores a pre-existing directory at + the clone target that is not a valid git repository; it now emits a + `Write-Warning` so the user knows why the install was skipped (#86). ## [0.4.1] - 2026-06-12 diff --git a/PSDepend/PSDependScripts/Git.ps1 b/PSDepend/PSDependScripts/Git.ps1 index 64c4e7a..3edd97f 100644 --- a/PSDepend/PSDependScripts/Git.ps1 +++ b/PSDepend/PSDependScripts/Git.ps1 @@ -132,7 +132,14 @@ if ($GottaTest) { $Branch = Invoke-ExternalCommand git -Arguments (Write-Output rev-parse --abbrev-ref HEAD) -Passthru $Commit = Invoke-ExternalCommand git -Arguments (Write-Output rev-parse HEAD) -Passthru Pop-Location - if ($Version -eq $Branch -or $Version -eq $Commit) { + if (-not $Branch) { + Write-Warning "[$RepoPath] exists but does not appear to be a valid git repository. Skipping [$DependencyName]." + if ($PSDependAction -contains 'Test' -and $PSDependAction.count -eq 1) { + return $false + } + $GottaInstall = $False + } + elseif ($Version -eq $Branch -or $Version -eq $Commit) { Write-Verbose "[$RepoPath] exists and is already at version [$Version]" if ($PSDependAction -contains 'Test' -and $PSDependAction.count -eq 1) { return $true diff --git a/Tests/Git.Type.Tests.ps1 b/Tests/Git.Type.Tests.ps1 index 848b94b..dd4e7e6 100644 --- a/Tests/Git.Type.Tests.ps1 +++ b/Tests/Git.Type.Tests.ps1 @@ -74,4 +74,46 @@ Describe 'Git script' { $result | Should -Be $false Should -Invoke -CommandName Invoke-ExternalCommand -ModuleName PSDepend -Times 0 } + + It 'Does not clone again when repo already exists at the correct version (idempotency)' { + $targetDir = (New-Item 'TestDrive:/git-idempotent' -ItemType Directory -Force).FullName + # Pre-create the repo directory as if a prior run cloned it + $null = New-Item (Join-Path $targetDir 'repo') -ItemType Directory -Force + $dep = New-PSDependFixture -DependencyName 'https://example.com/user/repo.git' -DependencyType 'Git' -Version 'main' -Target $targetDir + + InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } { + # rev-parse returns the branch name matching Version + Mock Invoke-ExternalCommand { + if ($Arguments -contains '--abbrev-ref') { return 'main' } + if ($Arguments -notcontains 'clone' -and $Arguments -notcontains '--abbrev-ref') { return 'abc1234' } + } + & $ScriptPath -Dependency $Dep + } + Should -Invoke -CommandName Invoke-ExternalCommand -ModuleName PSDepend -Times 0 -ParameterFilter { + $Arguments -contains 'clone' + } + Should -Invoke -CommandName Invoke-ExternalCommand -ModuleName PSDepend -Times 0 -ParameterFilter { + $Arguments -contains 'checkout' + } + } + + It 'Emits a warning and skips install when the repo path exists but is not a git repository' { + $targetDir = (New-Item 'TestDrive:/git-nongit' -ItemType Directory -Force).FullName + # Pre-create the directory but leave it empty (not a git repo) + $null = New-Item (Join-Path $targetDir 'repo') -ItemType Directory -Force + $dep = New-PSDependFixture -DependencyName 'https://example.com/user/repo.git' -DependencyType 'Git' -Version 'main' -Target $targetDir + + InModuleScope PSDepend -Parameters @{ Dep = $dep; ScriptPath = $script:ScriptPath } { + # rev-parse returns nothing (non-git directory) + Mock Invoke-ExternalCommand { } + Mock Write-Warning { } + & $ScriptPath -Dependency $Dep + } + Should -Invoke -CommandName Write-Warning -ModuleName PSDepend -Times 1 -ParameterFilter { + $Message -like '*does not appear to be a valid git repository*' + } + Should -Invoke -CommandName Invoke-ExternalCommand -ModuleName PSDepend -Times 0 -ParameterFilter { + $Arguments -contains 'clone' + } + } }