modules/WinGet-Merge.psm1
Set-StrictMode -Version 2 Import-Module "$PSScriptRoot\WinGet-Utils.psm1" [string]$CheckpointFilePath = "$PSScriptRoot\winget.{HOSTNAME}.checkpoint" [string]$PackageDatabase = "$PSScriptRoot\winget.packages.json" <# .DESCRIPTION Merge host-installed package IDs into "winget.packages.json". #> function Merge-WinGetRestore { param( # When set, the package ignore-file is not applied. [switch]$NoIgnore, # Skip prompts for confirmation to merge missing package IDs. [switch]$MergeAll, # Skip prompts for tagging new package IDs. [switch]$NoTags, # Skips performing a checkpoint. [switch]$NoCheckpoint ) if ($NoCheckpoint) { # Skip performing a checkpoint. } else { Checkpoint-WinGetSoftware } $checkpointFile = $CheckpointFilePath.Replace('{HOSTNAME}', $(hostname).ToLower()) if (-not(Test-Path $checkpointFile)) { Write-Error "No checkpoint file found." return } $installedPackages = Get-Content $checkpointFile | ConvertFrom-Json $installedPackages = @($installedPackages.Sources | Where-Object { $_.SourceDetails.Name -eq 'winget' }).Packages if (-not(Test-Path $PackageDatabase)) { Write-Error "A 'winget.packages.json' is required to use this cmdlet. Please see Initialize-WinGetRestore." return } $packages = Get-Content $PackageDatabase | ConvertFrom-Json $newPackages = $installedPackages.PackageIdentifier | Where-Object { $packages.PackageIdentifier -notcontains $_ } $newPackages = $newPackages | Sort-Object -Unique if ($NoIgnore) { # Skip ignore package filtering. } else { $ignorePackages = Get-WinGetSoftwareIgnores $newPackages = $newPackages | Where-Object { $ignorePackages -notcontains $_ } } $jsonModified = $false $newPackages | ForEach-Object { $merge = $true if (-not($MergeAll)) { $question = "Merge package '$_' into 'winget.packages.json'?" $choices = @( [System.Management.Automation.Host.ChoiceDescription]::new("&Yes", "Do merge") [System.Management.Automation.Host.ChoiceDescription]::new("&No", "Do not merge") ) $decision = $Host.UI.PromptForChoice($null, $question, $choices, 1) $merge = $decision -eq 0 } if ($merge) { $newEntry = [PSCustomObject]@{ PackageIdentifier = [string]$_ Tags = @() } if ($NoTags) { # Skip prompting user for tagging each new package. } else { Write-Output "Enter tags for package '$_'. An empty entry concludes data entry." while ($true) { $tagEntry = Read-Host "Enter a tag name" if ([string]::IsNullOrWhiteSpace($tagEntry)) { break } $newEntry.Tags += $tagEntry } } $packages += $newEntry $jsonModified = $true Write-Output "Added package '$_'" } else { Write-Output "Skipped package: '$_'" } } if ($jsonModified) { $packages | ConvertTo-Json | Out-File $PackageDatabase if ($?) { Write-Output "Saved configuration: '$PackageDatabase'" } } else { Write-Output "Nothing to merge to: '$PackageDatabase'" } } |