185 lines
7.5 KiB
PowerShell
185 lines
7.5 KiB
PowerShell
function Set-ChocoPackageSourceFeedsV2 {
|
|
<#
|
|
.SYNOPSIS
|
|
Assigns package sources to the $package.Feed of the packages passed in.
|
|
THIS IS A SIDE EFFECT because collections in PowerShell are byRef, not byValue
|
|
|
|
.PARAMETER Packages
|
|
Array of Package Objects to assign Feed members to
|
|
|
|
.PARAMETER Hostname
|
|
Hostname of computer ON WHICH to get sources and package list for those sources. Default is localhost.
|
|
|
|
.PARAMETER MissingPackageLogLevel
|
|
Whether to Write-Error or Write-Warning when there are missing packages. Default is ERROR.
|
|
#>
|
|
[CmdletBinding()]
|
|
Param(
|
|
[Parameter(Mandatory = $true)]
|
|
[object[]]$Packages,
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$Hostname = "localhost",
|
|
[Parameter(Mandatory = $false)]
|
|
[ValidateSet("ERROR", "WARNING")]
|
|
[string]$MissingPackageLogLevel = "ERROR",
|
|
[switch]$excludeDisabledSources
|
|
)
|
|
$logLead = (Get-logLeadName)
|
|
|
|
# Early out if all of the packages already have feeds.
|
|
if ($Packages.Feed -notcontains $null) {
|
|
Write-Warning "$logLead : All packages have feeds already, no work to do, returning early."
|
|
|
|
return
|
|
}
|
|
|
|
$PASSTHRU_CHOCOLATEY_PUBLIC_URL = Get-ChocoPublicPassThruFeedUrl
|
|
$REAL_CHOCOLATEY_PUBLIC_URL = "https://chocolatey.org/api/v2*"
|
|
Write-Host "$logLead : Now determining source feeds for packages."
|
|
|
|
# Grab feeds from the server, and filter out the chocolatey/nameless feeds.
|
|
$getChocoSourceArgs = @{ Hostname = $Hostname; }
|
|
if (!$excludeDisabledSources) {
|
|
$getChocoSourceArgs.includeDisabledSources = $true
|
|
}
|
|
|
|
# Grab feeds from the server, and filter out the chocolatey/nameless feeds.
|
|
$feeds = [array](Get-ChocolateySourcesV2 @getChocoSourceArgs)
|
|
|
|
# Get the public choco feed passthru.
|
|
$passthroughPublicFeed = $feeds | Where-Object { $_.Source -eq $PASSTHRU_CHOCOLATEY_PUBLIC_URL }
|
|
|
|
# Get the other feeds where Name, Source are not empty, are not Disabled and are not the Passthru feed.
|
|
$filteredFeeds = $feeds | Where-Object {
|
|
(![string]::IsNullOrWhiteSpace($_.Name) -and
|
|
![string]::IsNullOrWhiteSpace($_.Source)) -and
|
|
!$_.Disabled -and
|
|
$_.Source -ne $PASSTHRU_CHOCOLATEY_PUBLIC_URL -and
|
|
$_.Source -notlike $REAL_CHOCOLATEY_PUBLIC_URL
|
|
}
|
|
|
|
# Get feeds where (Name OR Source) is empty AND NOT Disabled. These are invalid feeds.
|
|
$invalidFeeds = $feeds | Where-Object {
|
|
([string]::IsNullOrWhiteSpace($_.Name) -or
|
|
[string]::IsNullOrWhiteSpace($_.Source)) -and
|
|
!$_.Disabled }
|
|
|
|
# Get any feeds that are Disabled.
|
|
$disabledFeeds = $feeds | Where-Object { $_.Disabled }
|
|
|
|
if (!(Test-IsCollectionNullOrEmpty $invalidFeeds)) {
|
|
Write-Warning "$logLead : the following feeds are misconfigured`n$($invalidFeeds.Name)"
|
|
}
|
|
|
|
if(Test-IsCollectionNullOrEmpty $filteredFeeds) {
|
|
Write-Error "$logLead : No filtered feeds found!"
|
|
throw "$logLead : No filtered feeds found!"
|
|
return
|
|
}
|
|
|
|
# These feeds were flagged as disabled so we'll let everyone know we're skipping them.
|
|
foreach ($disabledFeed in $disabledFeeds) {
|
|
Write-Host "$logLead : Feed '$($disabledFeed.Name)' is flagged as Disabled, ignoring."
|
|
}
|
|
|
|
# If there is not public choco feed configured, add one that is the Proget passthru.
|
|
if ($null -eq $passthroughPublicFeed) {
|
|
$properties = @{
|
|
Name = 'Chocolatey Passthrough'
|
|
Source = $PASSTHRU_CHOCOLATEY_PUBLIC_URL
|
|
Priority = 0
|
|
Disabled = $false
|
|
IsDefault = $true
|
|
IsSDK = $false
|
|
};
|
|
$passthroughPublicFeed = New-Object -TypeName PSObject -Prop $properties;
|
|
Write-Host "$logLead : Setting default choco passthru '$($passthroughPublicFeed.Name)' '$($passthroughPublicFeed.Source)'"
|
|
}
|
|
|
|
# Get all of the packages from each feed in parallel.
|
|
$feedPackageResults = Invoke-Parallel -objects $filteredFeeds -returnObjects -arguments $Hostname -script {
|
|
Param(
|
|
$sbFeed,
|
|
$sbHostname
|
|
)
|
|
|
|
# Collect the names of packages in this feed.
|
|
$feedName = $sbFeed.Name
|
|
$feedSource = $sbFeed.Source
|
|
$logLead = "[Set-ChocoPackageSourceFeedsV2]"
|
|
|
|
Write-Host "$logLead : Pulling packages names from source '$feedName' - '$feedSource'"
|
|
|
|
$scriptPackages = @()
|
|
$scriptPackages = Get-ChocoState -s $feedSource -pre
|
|
|
|
if(($scriptPackages.Count -eq 0) -or (($scriptPackages.Count -eq 1) -and ([string]::IsNullOrWhiteSpace($scriptPackages[0])))) {
|
|
$scriptPackages = $null
|
|
}
|
|
|
|
$result = @{
|
|
FeedName = $sbFeed.Name
|
|
Packages = $scriptPackages
|
|
}
|
|
return $result
|
|
}
|
|
|
|
if(!(Test-IsCollectionNullOrEmpty $feedPackageResults)) {
|
|
$feedPackageResults = $feedPackageResults | Where-Object { $null -ne ($_["Packages"]) }
|
|
}
|
|
|
|
# Match every package name to a feed.
|
|
$packageToFeed = @{}
|
|
|
|
foreach($feedResult in $feedPackageResults) {
|
|
$feedName = $feedResult["FeedName"]
|
|
$feed = $filteredFeeds | Where-Object { $_.Name -eq $feedName }
|
|
[array]$packagesInFeed = $feedResult["Packages"]
|
|
|
|
foreach ($feedPackage in $packagesInFeed) {
|
|
$packageName = $feedPackage.Name
|
|
if ($packageToFeed.ContainsKey($packageName)) {
|
|
$firstSourceName = $packageToFeed[$packageName].Name
|
|
Write-Error "$logLead : Multiple sources contain a package named '$packageName'. Found in sources '$firstSourceName' and '$feedName'"
|
|
}
|
|
$packageToFeed.Set_Item($packageName, $feed)
|
|
}
|
|
}
|
|
|
|
# Run back through all the packages, and assign feeds based on package names.
|
|
foreach ($pkg in $Packages) {
|
|
$packageName = $pkg.Name
|
|
if ($packageToFeed.ContainsKey($packageName)) {
|
|
$pkg.Feed = $packageToFeed.Get_Item($packageName)
|
|
} else {
|
|
# For "Disabled" choco sources, you can only query them using the source param with a feed URL
|
|
# For public packages, "exact" matching is recommended. OpenSSH returns 8 records, only 1 is actually "openssh"
|
|
Write-Host "$logLead : Checking chocolatey.org passthru for '$packageName'"
|
|
$packagePublicRecord = Get-ChocoState -source $PASSTHRU_CHOCOLATEY_PUBLIC_URL -packageName $packageName -pre -exact
|
|
if ($null -eq $packagePublicRecord) {
|
|
$pkg.Feed = $null
|
|
} else {
|
|
$pkg.Feed = $passthroughPublicFeed
|
|
Write-Warning "$logLead : Package ONLY found on passthru for public chocolatey feed '$packageName'"
|
|
}
|
|
}
|
|
|
|
if (!$pkg.Feed) {
|
|
Write-Warning "$logLead : Was not able to determine a source feed for package '$packageName'"
|
|
}
|
|
}
|
|
[string]$missingPackageOutputText = $null
|
|
$missingFeedPackages = $Packages | Where-Object { $null -eq $_.Feed }
|
|
foreach ($missingFeedPackage in $missingFeedPackages) {
|
|
$missingPackageOutputText += "$($missingFeedPackage.Name)|$($missingFeedPackage.Version)`n"
|
|
}
|
|
if (![string]::IsNullOrWhiteSpace($missingPackageOutputText)) {
|
|
if ($MissingPackageLogLevel -eq "ERROR") {
|
|
Write-Error "$logLead : Was not able to find the following package(s) in any feed:`n $missingPackageOutputText"
|
|
} else {
|
|
Write-Warning "$logLead : Was not able to find the following package(s) in any feed:`n $missingPackageOutputText"
|
|
}
|
|
}
|
|
Write-Host "$logLead : Package names matched to feeds."
|
|
}
|