NuGetPackage.psm1
# Copyright (c) 2024 Roger Brown. # Licensed under the MIT License. function NuGetPackage { [CmdletBinding(PositionalBinding=$False)] Param( [Parameter(Mandatory=$True)][string]$Source, [PSCredential]$Credential, [string]$Filter, [string]$Name, [string]$RequiredVersion, [switch]$AllVersions, [bool]$SaveVerb ) Process { if ($PSVersionTable.PSEdition -eq 'Desktop') { $IsWindows = $True } if ($IsWindows) { $NuGetConfigPath = "$env:APPDATA\NuGet\NuGet.Config" } else { $NuGetConfigPath = "$env:HOME/.nuget/NuGet/NuGet.Config", "$env:HOME/.config/NuGet/NuGet.Config" } $NuGetConfig = $Null foreach ($NuGetConfigFile in $NuGetConfigPath) { if (Test-Path -LiteralPath $NuGetConfigFile) { [xml]$NuGetConfig = Get-Content -LiteralPath $NuGetConfigFile break } } if (-not $NuGetConfig) { Write-Error "NuGet.Config not found" } $PackageSource = (Select-Xml -Xml $NuGetConfig -XPath "/configuration/packageSources/add[@key='$Source']").Node if (-not $PackageSource) { Write-Error "NuGet source $Source not found" } $PackageSourceUrl = $PackageSource.value if (-not $PackageSourceUrl) { Write-Error "No Source URL for $Source" } $args = @{ Uri = $PackageSourceUrl } $SourceUri = New-Object -TypeName 'System.Uri' -ArgumentList $PackageSourceUrl $PackageFilename = "$Name.$RequiredVersion.nupkg" if ($SourceUri.IsFile) { $FilePath = Join-Path -Path $SourceUri.LocalPath -ChildPath $PackageFilename if (Test-Path -LiteralPath $FilePath) { $PackageContent = "$PackageSourceUrl/$PackageFilename" } else { Write-Error "$FilePath not found" } } else { try { if ($Credential) { $args['Credential'] = $Credential } Write-Verbose "GET $PackageSourceUrl" $Index = Invoke-RestMethod @args } catch { $Response = $PSItem.Exception.Response if ($Response.StatusCode.Value__ -and ( -not $Credential )) { switch ($Response.StatusCode.Value__) { 401 { $UserName = (Select-Xml -Xml $NuGetConfig -XPath "/configuration/packageSourceCredentials/$Source/add[@key='Username']").Node $Password = (Select-Xml -Xml $NuGetConfig -XPath "/configuration/packageSourceCredentials/$Source/add[@key='ClearTextPassword']").Node if ($UserName -and $Password) { [securestring]$secStringPassword = ConvertTo-SecureString $Password.value -AsPlainText -Force $Credential = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList $UserName.value, $secStringPassword } else { $Message = "Provide credentials for NuGet source '$Source'" $WWWAuthenticate = $Response.Headers | Where-Object { $_.Key -eq 'WWW-Authenticate' } | ForEach-Object { $_.Value } if ($WWWAuthenticate) { $Realm = (Select-String -InputObject $WWWAuthenticate -Pattern 'realm="(.*?)"').Matches.Groups[1].value if ($Realm) { $Message = "Provide credentials for '$Realm'" } } $Credential = Get-Credential -Message $Message } if ($Credential) { try { $args['Credential'] = $Credential $Index = Invoke-RestMethod @args } catch { Write-Error $PSItem } } else { Write-Error "No credentials for $Source found" } } default { Write-Error $PSItem } } } else { Write-Error $PSItem } } $SearchQueryService = $Null foreach ($Resource in $Index.resources) { switch ($Resource.'@type') { { @('SearchQueryService', 'SearchQueryService/3.0.0-beta') -contains $_ } { $SearchQueryService = $Resource.'@id' if ($Filter -and $SearchQueryService) { $args['Body'] = @{ q = $Filter } } } } if ($SearchQueryService) { break } } if (-not $SearchQueryService) { Write-Error "SearchQueryService not found" } $args['Uri'] = $SearchQueryService if ($Filter) { Write-Verbose "GET $($SearchQueryService)?q=$Filter" } else { Write-Verbose "GET $SearchQueryService" } $QueryResult = Invoke-RestMethod @args $args.Remove('Body') $VersionInfo = $Null $PackageContent = $Null foreach ($Data in $QueryResult.Data) { if (($Data.id -eq $Name) -or (-not $Name)) { if ($SaveVerb -and ( -not $RequiredVersion )) { $RequiredVersion = $Data.version } if ($RequiredVersion -and $Name) { foreach ($Version in $Data.versions) { if ($Version.version -eq $RequiredVersion) { if ($SaveVerb) { $Uri = $Version.'@id' $args['Uri'] = $Uri Write-Verbose "GET $Uri" $VersionInfo = Invoke-RestMethod @args $PackageContent = $VersionInfo.packageContent $PackageFilename = "$($Data.id).$($Version.version).nupkg" [pscustomobject]@{ Version = $Version.version Name = $Data.id Source = $Source Description = $Data.description PackageContent = $PackageContent PackageFilename = $PackageFilename Credential = $Credential } } else { [pscustomobject]@{ Version = $Version.version Name = $Data.id Source = $Source Description = $Data.description } } } } } else { if ($AllVersions) { foreach ($Version in $Data.versions) { [pscustomobject]@{ Version = $Version.version Name = $Data.id Source = $Source Description = $Data.description } } } else { [pscustomobject]@{ Version = $Data.version Name = $Data.id Source = $Source Description = $Data.description } } } } } } } } function Find-NuGetPackage { [CmdletBinding(PositionalBinding=$False)] Param( [Parameter(Mandatory=$True)][string]$Source, [string]$Name, [PSCredential]$Credential, [string]$Filter, [string]$RequiredVersion, [switch]$AllVersions ) Process { $args = @{ Source = $Source } foreach ($Nvp in ('Name',$Name),('Credential',$Credential),('RequiredVersion',$RequiredVersion),('Filter',$Filter)) { if ($Nvp[1]) { $args[$Nvp[0]] = $Nvp[1] } } if ($AllVersions) { $args['AllVersions'] = $AllVersions } $ErrorActionOriginal = $ErrorActionPreference try { $ErrorActionPreference = 'Stop' NuGetPackage @args } catch { $ErrorActionPreference = $ErrorActionOriginal Write-Error $PSItem } } } function Save-NuGetPackage { [CmdletBinding(PositionalBinding=$False)] Param( [Parameter(Mandatory=$True)][string]$Source, [Parameter(Mandatory=$True)][string]$Name, [PSCredential]$Credential, [string]$Filter, [string]$RequiredVersion, [string]$Path, [string]$LiteralPath ) Process { $args = @{ Source = $Source Name = $Name SaveVerb = $True } foreach ($Nvp in ('Credential',$Credential),('RequiredVersion',$RequiredVersion),('Filter',$Filter)) { if ($Nvp[1]) { $args[$Nvp[0]] = $Nvp[1] } } $ErrorActionOriginal = $ErrorActionPreference try { $ErrorActionPreference = 'Stop' if ($Path -and $LiteralPath) { Write-Error "Can't provide both Path and LiteralPath" } if ($Path) { $ResolvedPath = Resolve-Path -Path $Path if ($ResolvedPath.Count -ne 1) { Write-Error "Path '$Path' was ambiguous" } $LiteralPath = $ResolvedPath } if ($LiteralPath -and -not ( Test-Path -LiteralPath $LiteralPath -PathType Container )) { Write-Error "Directory '$LiteralPath' not found" } $Results = New-Object -TypeName 'System.Collections.ArrayList' NuGetPackage @args | ForEach-Object { $Uri = $_.PackageContent $PackageFilename = $_.PackageFilename if ($LiteralPath) { $OutFile = Join-Path -Path $LiteralPath -ChildPath $PackageFilename } else { $OutFile = $PackageFilename } $args = @{ OutFile = $OutFile Uri = $Uri } if ($_.Credential) { $args['Credential'] = $_.Credential } Write-Verbose "GET $Uri" Invoke-WebRequest @args $Results += $PackageFilename } if (-not $Results) { Write-Error 'No results' } } catch { $ErrorActionPreference = $ErrorActionOriginal Write-Error $PSItem } } } Export-ModuleMember -Function 'Find-NuGetPackage','Save-NuGetPackage' |