Public/Nuget/Update-NugetPackage.ps1


function Update-NugetPackage {
    [cmdletbinding()]
    param(
        [parameter(ValueFromPipeline, ParameterSetName = "SourcePath")]
        [string]$SourcePath = ".",
        [parameter(ParameterSetName = "projects")]
        [System.IO.FileInfo[]]$projects,
        [string]$RepositoryPath,
        [parameter()]
        [string]$Filter = ".*",
        [string]$ExcludeFilter ,
        [string]$sources = ((Get-PackageSourceLocations Nuget) -join ";")
    )
    
    if ($RepositoryPath) {
        Write-Host "PackagesConfig:" -f Blue 
        Update-NugetPackagesConfig $SourcePath $RepositoryPath $Filter $ExcludeFilter $sources
    }
    
    
    if (!$projects) {
        $projects = Get-ChildItem $SourcePath *.csproj -Recurse 
    }
    Write-Host "projects:" -f blue
    $projects | Select-Object -expandProperty baseName
    $packages = $projects | ForEach-Object {
        $p = (Get-PackageReference $_.FullName).Include | Where-Object { $_ -and $_ -match $Filter }
        if ($ExcludFilter) {
            $p | Where-Object { $_ -notmatch $ExcludeFilter }
        }
        else {
            $p
        }
    } | Sort-Object -Unique

Write-Host "packages:" -f blue
$packages
$metadata = $packages | ForEach-Object {
    Get-NugetPackageSearchMetadata $_ $sources
} | Get-SortedPackageByDependencies
        
$packagesToAdd = GetPackagesToAdd $projects $Filter $ExcludeFilter
Write-Host "packagesToAdd:$($packagesToAdd.Count)" -ForegroundColor Blue
$packagesToAdd 
Write-Host "`r`n`r`n"
$concurrencyLimit = [System.Environment]::ProcessorCount - 2
while ($packagesToAdd) {
    $notPackagesToAdd = $packagesToAdd | Invoke-Parallel -LimitConcurrency $concurrencyLimit -Script {
        $projectPath = $_.ProjectPath
        $p = $_.Package
        $s = $_.Sources
        $v = $_.Version
        $nuget = Get-NugetPath
        $output = "dotnet add $projectPath package $p -v $v -s $s`r`n"
        try {
            $output = dotnet add $projectPath package $p -v $v -s $s -n
            if ($output -like "*error*") {
                [PSCustomObject]@{
                    Package = $_
                    Error   = $output
                }
            }
        }
        catch {
                
        }
    }
        
        
    Write-Host "Not-PackagesToAdd: $($notPackagesToAdd.Count)" -ForegroundColor Red
    $notPackagesToAdd.Package | Out-String
    Write-Host "Error:" -ForegroundColor Red
    $notPackagesToAdd.Error | Out-String

    Write-Host "`r`n`r`n"
    Start-Sleep 1
    $packagesToAdd = GetPackagesToAdd $projects $Filter $ExcludeFilter
    Write-Host "packagesToAdd:$($packagesToAdd.Count)" -ForegroundColor Blue
    $packagesToAdd 
}

}
function GetPackagesToAdd($projects, $Filter, $ExcludeFilter) {
    $projects | ForEach-Object {
        $csprojPath = $_.FullName
        $csprojName = $_.BaseName
        Get-PackageReference $csprojPath | Where-Object {
            $r = $_.Include -and $_.Include -match $Filter
            if ($ExcludeFilter -and $r) {
                $_.Include -notmatch $ExcludeFilter
            }
            else {
                $r
            }
        } | ForEach-Object {
            $p = $_.Include
            $m = $metadata | Where-Object { $_.Identity.Id -eq $p }
            $latestVersion = (Get-NugetPackageMetadataVersion $m).version
            $installedVersion = $_.Version
            if ($latestVersion -ne $installedVersion) {
                Write-Host "Updating $csprojName $p $installedVersion to $latestVersion" -f Green
                [PSCustomObject]@{
                    ProjectPath = $csprojPath
                    Package     = $p
                    Version     = $latestVersion
                    Sources     = $sources
                }
            }
        }
}
}
function Update-NugetPackagesConfig {
    [CmdletBinding()]
    param (
        [parameter(ValueFromPipeline)]
        [string]$SourcePath = ".",
        [string]$RepositoryPath,
        [parameter()]
        [string]$Filter = ".*",
        [string]$ExcludFilter,
        [string]$sources = ((Get-PackageSourceLocations Nuget) -join ";")
    )
    
    begin {
    }
    
    process {
        $configs = Get-ChildItem $sourcePath packages.config -Recurse | ForEach-Object {
            [PSCustomObject]@{
                Content = [xml]$(Get-Content $_.FullName)
                Config  = $_
            }
        }
    
        $metadatas = $configs.Content.packages.package.id | Where-Object { $_ -match $Filter -and $_ -notmatch $ExcludFilter } | Select-Object -Unique | Get-NugetPackageSearchMetadata -Source $sources
        $metadatas | ForEach-Object {
            [PSCustomObject]@{
                Title   = $_.Title
                Version = $_.Identity.Version.Version
            }
        }
        $packages = $configs | ForEach-Object {
            $_.Config.FullName
            $config = $_.Config
            $_.Content.packages.package | Where-Object { $_.id -like $filter } | ForEach-Object {
                $packageId = $_.Id
                $metadata = $metadatas | Where-Object { $_.Identity.Id -eq $packageId }
                if ($metadata) {
                    $csproj = Get-ChildItem $config.DirectoryName *.csproj | Select-Object -first 1
                    $latestVersion = (Get-NugetPackageMetadataVersion $metadata).version
                    [PSCustomObject]@{
                        Id         = $packageId
                        NewVersion = $latestVersion
                        Config     = $config.FullName
                        csproj     = $csproj.FullName
                        Version    = $_.Version
                    }
                }
            }
        } | Where-Object { $_.NewVersion -and ($_.Version -ne $_.NewVersion) }
    $sortedPackages = $packages | Group-Object Config | ForEach-Object {
        $p = [PSCustomObject]@{
            Packages = ($_.Group | Get-SortedPackageByDependencies)
        }
        $p
    } 
    
    
    $sortedPackages | Invoke-Parallel -activityName "Update all packages" -VariablesToImport @("RepositoryPath", "sources") -Script {
        ($_.Packages | ForEach-Object {
                if ($RepositoryPath) {
                    & (Get-NugetPath) Update $_.Config -Id $_.Id -Version $($_.NewVersion) -Source $sources -NonInteractive -RepositoryPath $RepositoryPath
                }
                else {
                    & (Get-NugetPath) Update $_.Config -Id $_.Id -Version $($_.NewVersion) -Source $sources -NonInteractive 
                }
            
            })
    }
}
    
end {
}
}

function Get-SortedPackageByDependencies {
    [CmdletBinding()]
    param (
        [parameter(ValueFromPipeline, Mandatory)]
        $psObj
    )
    begin {
        $all = New-Object System.Collections.ArrayList
    }
    
    process {
        $all.Add($psObj) | Out-Null
    }
    
    end {
        $list = New-Object System.Collections.ArrayList
        
        while ($all.Count) {
            $all | ForEach-Object {
                $obj = $_
                $deps = $obj.DependencySets.Packages | Select-Object -ExpandProperty Id
                $exist = $all | Select-Object -ExpandProperty Identity | Where-Object { $deps -contains $_.Id }
                if (!$exist) {
                    $list.Add($obj) | Out-Null
                }
            }
            $list | ForEach-Object {
                $all.Remove($_) | Out-Null
            }
        }
        $list | ForEach-Object { $_ }
    }
}