SourceTypes/PSGallery/PSGallery.psm1
Microsoft.PowerShell.Core\Set-StrictMode -Version Latest $script:PSGetSourceType = "PSGallery" $script:NuGetBinariesPath="$env:LOCALAPPDATA\Microsoft\Windows\PowerShell\PowerShellGet" $script:NuGetClient = "$script:NuGetBinariesPath\NuGet.exe" $script:NuGetAssembly = $null #These two variables allow us to change the Source and Publish URIs for PSGallery $PSGallerySourceUri = "https://dtlgalleryint.cloudapp.net/api/v2/" $PSGalleryPublishUri = $PSGallerySourceUri+"package/" Microsoft.PowerShell.Utility\Import-LocalizedData LocalizedData -filename PSGet.Resource.psd1 -BaseDirectory "$PSScriptRoot\..\.." # Check if current user is running with elevated privileges function Test-RunningAsElevated { [CmdletBinding()] [OutputType([bool])] Param() $wid=[System.Security.Principal.WindowsIdentity]::GetCurrent() $prp=new-object System.Security.Principal.WindowsPrincipal($wid) $adm=[System.Security.Principal.WindowsBuiltInRole]::Administrator return $prp.IsInRole($adm) } # Utility to throw an errorrecord function ThrowError { param ( [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $ExceptionName, [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $ExceptionMessage, [System.Object] $ExceptionObject, [parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $ErrorId, [parameter(Mandatory = $true)] [ValidateNotNull()] [System.Management.Automation.ErrorCategory] $ErrorCategory ) $exception = New-Object $ExceptionName $ExceptionMessage; $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $ErrorId, $ErrorCategory, $ExceptionObject throw $errorRecord } function Install-NuGetClientBinaries { $NuGetClientSource = "https://nuget.org/nuget.exe" $ShouldContinueQueryMessage = $LocalizedData.InstallNuGetBinariesShouldContinueQuery -f @($script:NuGetBinariesPath,$script:NuGetBinariesPath) if($PSCmdlet.ShouldContinue($ShouldContinueQueryMessage, $LocalizedData.InstallNuGetBinariesShouldContinueCaption)) { Write-Verbose -Message $LocalizedData.DownloadingNugetBinaries $null = Microsoft.PowerShell.Management\New-Item -Path $script:NuGetBinariesPath -ItemType Directory -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false if(-not (Microsoft.PowerShell.Management\Test-Path $script:NuGetClient)) { # Download the NuGet.exe from https://nuget.org/NuGet.exe $null = Microsoft.PowerShell.Utility\Invoke-WebRequest -Uri $NuGetClientSource -OutFile $script:NuGetClient } } if(-not (Microsoft.PowerShell.Management\Test-Path $script:NuGetClient)) { $message = $LocalizedData.CouldNotInstallNuGetBinaries -f @($script:NuGetBinariesPath) ThrowError -ExceptionName "System.InvalidOperationException" ` -ExceptionMessage $message ` -ErrorId "CouldNotInstallNuGetBinaries" ` -ErrorCategory InvalidOperation } } function New-PSGetItemInfo { param( [Parameter(Mandatory=$true)] [ValidateNotNull()] $packageInfo ) $PSGetItemInfo = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{ Name = $packageInfo.Id Version = [Version]$packageInfo.Version.ToString() Description = $packageInfo.Description Author = $packageInfo.Authors CompanyName = $packageInfo.Owners Copyright = $packageInfo.CopyRight LicenseUri = $packageInfo.LicenseUrl ProjectUri = $packageInfo.ProjectUrl IconUri = $packageInfo.IconUrl Tag = $packageInfo.Tags -split ' ' ReleaseNotes = $packageInfo.ReleaseNotes # Few properties are not avialable for packages hosted on local directory based NuGet repository DateUpdated = if(Get-Member -InputObject $packageInfo -Name LastUpdated) { $packageInfo.LastUpdated.LocalDateTime } else { $packageInfo.Published.LocalDateTime } RequiredModules = if(Get-Member -InputObject $packageInfo -Name Dependencies) { $packageInfo.Dependencies } else { $packageInfo.DependencySets } DownloadUri = if(Get-Member -InputObject $packageInfo -Name DownloadUrl) { $packageInfo.DownloadUrl } else { $null } Hash = if(Get-Member -InputObject $packageInfo -Name PackageHash) { $packageInfo.PackageHash } else { $null } HashAlgorithm = if(Get-Member -InputObject $packageInfo -Name PackageHashAlgorithm) { $packageInfo.PackageHashAlgorithm } else { $null } SourceUri = $PSGallerySourceUri SourceType = $script:PSGetSourceType }) $PSGetItemInfo.PSTypeNames.Insert(0, "Microsoft.PowerShell.Commands.PSGetItemInfo") $PSGetItemInfo } function Get-PSGetItemInfo { [CmdletBinding()] [OutputType("PSCustomObject")] param( [Parameter(Mandatory=$true)] [ValidateNotNull()] $Name, [Parameter(Mandatory=$true)] [ValidateNotNull()] $RepoObject, [Parameter()] [ValidateNotNull()] [Version] $Version ) if($Version) { $packageInfo = [NuGet.PackageRepositoryExtensions]::FindPackage($RepoObject, $Name, $Version) } else { $packageInfo = [NuGet.PackageRepositoryExtensions]::FindPackage($RepoObject, $Name) } if($packageInfo) { New-PSGetItemInfo -packageInfo $packageInfo } } function Test-WildcardPattern { [CmdletBinding()] [OutputType([bool])] param( [Parameter(Mandatory=$true)] [ValidateNotNull()] $Name ) return [System.Management.Automation.WildcardPattern]::ContainsWildcardCharacters($Name) } function Find-PSGetExtModule { [CmdletBinding(DefaultParameterSetName='ModuleName',PositionalBinding=$false)] Param ( [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName='ModuleName')] [string[]] $Name, [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName='FullyQualifiedName')] [ValidateNotNullOrEmpty()] [HashTable[]] $FullyQualifiedName ) Begin { if(-not (Microsoft.PowerShell.Management\Test-Path $script:NuGetClient)) { Install-NuGetClientBinaries } if(-not $script:NuGetAssembly) { $tempNuGetExePath = "$env:TEMP\NuGet_ForPSGet.exe" if(-not (Microsoft.PowerShell.Management\Test-Path -Path $tempNuGetExePath)) { Microsoft.PowerShell.Management\Copy-Item -Path $script:NuGetClient -Destination $tempNuGetExePath -Force ` -Confirm:$false -WhatIf:$false ` -ErrorAction SilentlyContinue -WarningAction SilentlyContinue } $script:NuGetAssembly = [System.Reflection.Assembly]::LoadFile($tempNuGetExePath) } # Create repository object for getting module metadata from local repository or from gallery service if(Microsoft.PowerShell.Management\Test-Path $PSGallerySourceUri) { $NDSPackageRepo = New-Object NuGet.LocalPackageRepository $PSGallerySourceUri } else { $psGalleryUri = $null try { $request = [System.Net.WebRequest]::Create($PSGallerySourceUri) $request.Method = 'GET' $response = $request.GetResponse() $psGalleryUri = $response.ResponseUri $response.Close() } catch { # Ignoring exceptions } if($psGalleryUri -eq $null) { $psGalleryUri = New-Object System.Uri $PSGallerySourceUri } $NDSPackageRepo = New-Object Nuget.DataServicePackageRepository $psGalleryUri } # Wildcard pattern matching configuration. $wildcardOptions = [System.Management.Automation.WildcardOptions]::CultureInvariant -bor ` [System.Management.Automation.WildcardOptions]::IgnoreCase } Process { switch($PSCmdlet.ParameterSetName) { "ModuleName" { if(-not $Name) { Write-Verbose -Message $LocalizedData.FindingAvailableModules $result = & $script:NuGetClient list -source $PSGallerySourceUri -NonInteractive if($result -eq "No packages found.") { Write-Verbose -Message $LocalizedData.NoModulesFound return } Write-Verbose -Message ($LocalizedData.FoundModules -f $result.count) foreach($line in $result) { # each line in results has two parts: name version $metadata = $line.Split() Get-PSGetItemInfo -Name $metadata[0] -RepoObject $NDSPackageRepo } } else { foreach($artifactName in $Name) { if(Test-WildcardPattern -Name $artifactName) { # NuGet does not support PowerShell/POSIX style wildcards and supports only '*' in names # Replace the range from '[' - to ']' with * and ? with * then wildcard pattern is applied on the results from NuGet.exe $tempName = $artifactName $squareBracketPattern = [System.Text.RegularExpressions.Regex]::Escape("[") + "(.*?)]" $matches = [System.Text.RegularExpressions.Regex]::Matches($tempName, $squareBracketPattern) $matches | Microsoft.PowerShell.Core\ForEach-Object {$tempName = $tempName.Replace($_, "*")} $tempName = $tempName.Replace("?", "*") $searchTerm = "$tempName" } else { $searchTerm = "id:$artifactName" } $moduleFound = $false $result = & $script:NuGetClient list $searchTerm -source $PSGallerySourceUri -NonInteractive if($result -ne "No packages found.") { $wildcardPattern = New-Object System.Management.Automation.WildcardPattern $artifactName,$wildcardOptions foreach($line in $result) { $metadata = $line.Split() if($wildcardPattern.IsMatch($metadata[0])) { Get-PSGetItemInfo -Name $metadata[0] -RepoObject $NDSPackageRepo Write-Verbose -Message ($LocalizedData.FoundModuleWithVersion -f ($metadata[0], $metadata[1])) $moduleFound = $true } } } if(-not $moduleFound) { $message = $LocalizedData.ModuleNotFound -f ($artifactName) if(-not (Test-WildcardPattern -Name $artifactName)) { Write-Error -Message $message -ErrorId "ModuleNotFound" -Category InvalidOperation } Write-Verbose -Message $message } } } break } "FullyQualifiedName" { foreach($fqName in $FullyQualifiedName) { if($fqName.ContainsKey("RequiredVersion")) { $searchTerm = "$($fqName.ModuleName)" } else { $searchTerm = "id:$($fqName.ModuleName)" } $RequiredVersion = $null $ModuleVersion = $null if($fqName.ContainsKey("RequiredVersion")) { $RequiredVersion = $fqName.RequiredVersion $result = & $script:NuGetClient list $searchTerm -AllVersions -source $PSGallerySourceUri -NonInteractive } else { $ModuleVersion = $fqName.ModuleVersion $result = & $script:NuGetClient list $searchTerm -source $PSGallerySourceUri -NonInteractive } $moduleFound = $false if($result -ne "No packages found.") { foreach($line in $result) { $metadata = $line.Split() if($metadata[0] -like $fqName.ModuleName -and (($RequiredVersion -and ([Version]$metadata[1] -eq $RequiredVersion)) -or ($ModuleVersion -and ([Version]$metadata[1] -ge $ModuleVersion))) ) { Get-PSGetItemInfo -Name $metadata[0] -RepoObject $NDSPackageRepo -Version $([Version]$metadata[1]) Write-Verbose -Message ($LocalizedData.FoundModuleWithVersion -f ($metadata[0], $metadata[1])) $moduleFound = $true } } } if(-not $moduleFound) { if($RequiredVersion) { $message = $LocalizedData.ModuleNotFoundWithRequiredVersion -f ($fqName.ModuleName, $RequiredVersion) Write-Error -Message $message -ErrorId "ModuleNotFoundWithRequiredVersion" -Category InvalidOperation } else { $message = $LocalizedData.ModuleNotFoundWithMinimumVersion -f ($fqName.ModuleName, $ModuleVersion) Write-Error -Message $message -ErrorId "ModuleNotFoundWithMinimumVersion" -Category InvalidOperation } continue } } break } } } } function Get-PSGetExtModule { [CmdletBinding(PositionalBinding=$false)] [OutputType([Bool])] Param ( [Parameter(Mandatory=$true)] [ValidateNotNull()] [PSCustomObject] $PSGetItemInfo, [Parameter(Mandatory=$true)] [ValidateNotNull()] [string] $OutputDirectory ) if(-not (Microsoft.PowerShell.Management\Test-Path $script:NuGetClient)) { Install-NuGetClientBinaries } $output = & $script:NuGetClient install $PSGetItemInfo.Name -Version $PSGetItemInfo.Version -source $PSGallerySourceUri -OutputDirectory $OutputDirectory -ExcludeVersion -NonInteractive if($LASTEXITCODE) { return $false } $moduleBase = Microsoft.PowerShell.Management\Join-Path $OutputDirectory $PSGetItemInfo.Name if(Microsoft.PowerShell.Management\Test-Path $moduleBase) { Microsoft.PowerShell.Management\Remove-Item -Path "$moduleBase\*.nupkg" -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false } return $true } function Get-EscapedString { [CmdletBinding()] [OutputType([String])] Param ( [Parameter()] [string] $ElementValue ) return [System.Security.SecurityElement]::Escape($ElementValue) } function Publish-PSGetExtModule { [CmdletBinding(PositionalBinding=$false)] Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [PSModuleInfo] $PSModuleInfo, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $NugetApiKey, [Parameter()] [string] $ReleaseNotes, [Parameter()] [string[]] $Tag, [Parameter()] [string] $LicenseUri, [Parameter()] [string] $IconUri, [Parameter()] [string] $ProjectUri ) if(-not (Microsoft.PowerShell.Management\Test-Path $script:NuGetClient)) { Install-NuGetClientBinaries } # Populate the nuspec elements $nuspec = @" <?xml version="1.0"?> <package > <metadata> <id>$(Get-EscapedString -ElementValue $PSModuleInfo.Name)</id> <version>$($PSModuleInfo.Version)</version> <authors>$(Get-EscapedString -ElementValue $PSModuleInfo.Author)</authors> <owners>$(Get-EscapedString -ElementValue $PSModuleInfo.CompanyName)</owners> <description>$(Get-EscapedString -ElementValue $PSModuleInfo.Description)</description> <releaseNotes>$(Get-EscapedString -ElementValue $ReleaseNotes)</releaseNotes> <copyright>$(Get-EscapedString -ElementValue $PSModuleInfo.Copyright)</copyright> <tags>$(if($Tag){ Get-EscapedString -ElementValue ($Tag -join ' ')})</tags> $(if($LicenseUri){ "<licenseUrl>$(Get-EscapedString -ElementValue $LicenseUri)</licenseUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance>" }) $(if($ProjectUri){ "<projectUrl>$(Get-EscapedString -ElementValue $ProjectUri)</projectUrl>" }) $(if($IconUri){ "<iconUrl>$(Get-EscapedString -ElementValue $IconUri)</iconUrl>" }) <dependencies> </dependencies> </metadata> </package> "@ try { $NupkgPath = "$($PSModuleInfo.ModuleBase)\$($PSModuleInfo.Name).$($PSModuleInfo.Version.ToString()).nupkg" $NuspecPath = "$($PSModuleInfo.ModuleBase)\$($PSModuleInfo.Name).nuspec" # Remove existing nuspec and nupkg files Microsoft.PowerShell.Management\Remove-Item $NupkgPath -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false Microsoft.PowerShell.Management\Remove-Item $NuspecPath -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false Microsoft.PowerShell.Management\Set-Content -Value $nuspec -Path $NuspecPath # Create .nupkg file $output = & $script:NuGetClient pack $NuspecPath -OutputDirectory $PSModuleInfo.ModuleBase if($LASTEXITCODE) { $message = $LocalizedData.FailedToCreateCompressedModule -f ($output) Write-Error -Message $message -ErrorId "FailedToCreateCompressedModule" -Category InvalidOperation return } # Publish the .nupkg to gallery $output = & $script:NuGetClient push $NupkgPath -source $PSGalleryPublishUri -NonInteractive -ApiKey $NugetApiKey if($LASTEXITCODE) { $message = $LocalizedData.FailedToPublish -f ($output) Write-Error -Message $message -ErrorId "FailedToPublishTheModule" -Category InvalidOperation } else { $message = $LocalizedData.PublishedSuccessfully -f ($PSModuleInfo.Name) Write-Verbose -Message $message } } finally { Microsoft.PowerShell.Management\Remove-Item $NupkgPath -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false Microsoft.PowerShell.Management\Remove-Item $NuspecPath -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue -Confirm:$false -WhatIf:$false } } Export-ModuleMember -Function * -Alias * -Variable PSGallerySourceUri,PSGalleryPublishUri |