Last active
March 30, 2025 16:32
-
-
Save Nejat/6cb42f098320cb2fcb57a4e1728ca29e to your computer and use it in GitHub Desktop.
Lists and optionally upgrades available updates. Skips Unknown versions or anything in the skip list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
# provide a configuration file to define package handling | |
[string] $skipFile = "wngt-cfg", | |
# true to upgrade eligible packages, false dry run | |
[switch] $upgrade = $false | |
) | |
# adjust buffer size of output, really don't know if this helps ¯\_(ツ)_/¯ | |
if ($Host -and $Host.UI -and $Host.UI.RawUI) { | |
$rawUI = $Host.UI.RawUI | |
$oldSize = $rawUI.BufferSize | |
$typeName = $oldSize.GetType( ).FullName | |
$newSize = New-Object $typeName (500, $oldSize.Height) | |
$rawUI.BufferSize = $newSize | |
} | |
# get raw output of available upgrades, not power-shell native yet | |
[string] $rawOutput = winget upgrade --source winget --include-unknown | out-string -Width 5000 | |
# split raw output into lines | |
[string[]] $source = $rawOutput.Split([System.Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries) | |
# check if available upgrades succeeded, otherwise display message to user | |
if ($lastExitCode -ne 0) { | |
Write-Host | |
Write-Host checking winget upgrade failed, try again -ForegroundColor Red | |
Write-Host | |
exit $lastExitCode | |
} | |
# load and parse a skip list definition file if it exists, otherwise ignore skips | |
[PSCustomObject[]] $skip = if (Test-Path -Path $skipFile -PathType Leaf) { | |
Get-Content $skipFile | ForEach-Object { | |
[string[]] $parts = $_.Split('#') | |
[PSCustomObject] @{ | |
Skip = $parts[0].Trim() | |
Comment = $parts[1].Trim() | |
} | |
} | |
} else { | |
@() # otherwise $skip is null | |
} | |
# check if package matches any of the listed skip packages | |
function Skip-Update { | |
param ([string] $name) | |
foreach ($skipped in $skip) { | |
[string] $check = "*{0}*" -f $skipped.Skip | |
if ($name -like $check) { | |
return $skipped.Comment | |
} | |
} | |
return "" | |
} | |
# available upgrades | |
[PSCustomObject[]] $updates = @() | |
# all the indexes of column titles for parsing in current grouping | |
[int32] $idIndex = -1 | |
[int32] $currentIndex = -1 | |
[int32] $availableIndex = -1 | |
[bool] $searching = $true | |
$source | Select-Object| ForEach-Object { | |
# if search check if it's a title line | |
if ($searching -and $_.Contains("Id") -and $_.Contains("Version") -and $_.Contains("Available")) { | |
$idIndex = $_.IndexOf("Id") | |
$currentIndex = $_.IndexOf("Version") | |
$availableIndex = $_.IndexOf("Available") | |
$searching = $false | |
} else { | |
# if in section and not a separator line, look for updates | |
if (-not $searching -and -not ($_.StartsWith("---") -and $_.EndsWith("---"))) { | |
# if the line is long enough and the line has an upgrade version | |
if ($_.Length -gt $availableIndex -and $_.SubString($availableIndex, $_.Length - $availableIndex).Trim() -match "\d+(\.\d+)?") { | |
#parse package update information | |
[string] $name = $_.SubString(0, $idIndex).Trim() | |
[string] $id = $_.SubString($idIndex, $currentIndex - $idIndex).Trim() | |
[string] $current = $_.SubString($currentIndex, $availableIndex - $currentIndex).Trim() | |
[string] $available = $_.SubString($availableIndex, $_.Length - $availableIndex).Trim() | |
$updates += [PSCustomObject] @{ | |
Name = $name | |
Id = $id | |
Current = $Current | |
Available = $available | |
Skip = Skip-Update $name | |
} | |
} else { | |
#if not, assume you're done with this section and start searching for the next section | |
$idIndex = -1 | |
$currentIndex = -1 | |
$availableIndex = -1 | |
$searching = $true | |
} | |
} | |
} | |
} | |
# check if updates exist | |
if ($updates.Length -lt 1) { | |
Write-Host | |
Write-Host no upgrades available | |
Write-Host | |
exit | |
} | |
# determine the widest package name for column padding | |
[int32] $namePadding = ($updates | ForEach-Object { $_.Name.Length } | Measure-Object -Maximum | Select-Object -Property Maximum).Maximum + 2 | |
# determin the widest package version for column padding | |
[int32] $versionPadding = ($updates | ForEach-Object { [math]::Max($_.Current.Length, $_.Available.Length) } | Measure-Object -Maximum | Select-Object -Property Maximum).Maximum + 2 | |
# const status width padding | |
[int32] $statusWidth = 42 # ironic? or cosmic? =P | |
#table variable size column titles | |
[string] $nameTitle = "Name" | |
[string] $currentTitle = "Current" | |
[string] $availableTitle = "Available" | |
[int32] $extraPadding = 2 | |
# account for padding shorter than titles | |
$namePadding = [Math]::Max($namePadding, $nameTitle.Length + $extraPadding) | |
$versionPadding = [Math]::Max([Math]::Max($versionPadding, $currentTitle.Length + $extraPadding), $availableTitle.Length + $extraPadding) | |
# write table column titles | |
Write-Host | |
Write-Host $nameTitle.PadRight($namePadding, ' ') $currentTitle.PadLeft($versionPadding, ' ') $availableTitle.PadLeft($versionPadding, ' ') " Status" | |
Write-Host ("-" * $namePadding) ("-" * $versionPadding) ("-" * $versionPadding) " " ("-" * $statusWidth) | |
Write-Host | |
[int32] $failed = 0; | |
# process each package | |
foreach ($package in $updates) { | |
# output package info coumns | |
Write-Host $package.Name.PadRight($namePadding) $package.Current.PadLeft($versionPadding, ' ') $package.Available.PadLeft($versionPadding, ' ') "- " -NoNewline | |
# check if package should be skipped? | |
if ($package.Skip.Length -gt 0) { | |
# output package status | |
if ($upgrade) { | |
Write-Host "skipping" -ForegroundColor DarkYellow -NoNewline | |
} else { | |
Write-Host "skip" -ForegroundColor DarkYellow -NoNewline | |
} | |
Write-Host ";" $package.Skip | |
if ($upgrade) { Write-Host } | |
} else { | |
# check if package version is unknown | |
if ($package.Current -eq "Unknown") { | |
# output package status | |
Write-Host "skipping unknown version, check manually" -ForegroundColor Cyan | |
if ($upgrade) { Write-Host } | |
} else { | |
# temporary check if any properties have unicode garbled text | |
# this is only until winget piped output is fixed or supports power-shell natively | |
[bool] $garbled = ( | |
$package.Name.EndsWith("ΓÇ") -or | |
$package.Id.EndsWith("ΓÇ") -or $package.Id.StartsWith("ª ") -or | |
$package.Current.EndsWith("ΓÇ") -or $package.Current.StartsWith("ª ") -or | |
$package.Available.EndsWith("ΓÇ") -or $package.Available.StartsWith("ª ") | |
) | |
# check if packages should upgraded | |
if ($upgrade) { | |
# check if any property is garbled | |
if ($garbled) { | |
# output package status and continue to next package | |
Write-Host "skipping, garbled identifiers prevents update" -ForegroundColor Yellow | |
} else { | |
# perform package upgrade, capture output | |
# [string[]] $result = winget upgrade --exact --name """$($package.Name)""" --id """$($package.Id)""" --version """$($package.Available)""" --source winget | |
[string[]] $result = winget upgrade --id $package.Id --source winget | |
# check if package upgrade succeeded and output package status accordingly | |
if ($lastExitCode -eq 0) { | |
Write-Host "updated" -ForegroundColor Blue | |
} else { | |
$failed += 1 | |
Write-Host "failed to update" -ForegroundColor Red | |
Write-Host | |
# demonstrate command used for upgrade | |
# Write-Host ">" winget upgrade --exact --name """$($package.Name)""" --id """$($package.Id)""" --version """$($package.Available)""" --source winget -ForegroundColor Yellow | |
Write-Host ">" winget upgrade --id $package.Id --source winget -ForegroundColor Yellow | |
Write-Host | |
# output captured output from package upgrade | |
# foreach ($line in $result) { | |
# Write-Host $line -ForegroundColor DarkGray | |
# } | |
Write-Host $result[-1] | |
} | |
} | |
Write-Host | |
} else { | |
# check if any property is garbled and output package status accordingly | |
if ($garbled) { | |
Write-Host "skipping new version, garbled identifiers prevent update" -ForegroundColor Yellow | |
} else { | |
Write-Host "new version available" -ForegroundColor Blue | |
} | |
} | |
} | |
} | |
} | |
if ($failed -gt 0) { | |
Write-Host "* it's possible failed upgrades might require admin privledges" -ForegroundColor Yellow | |
} | |
Write-Host |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment