modules/WinGet-Initialize.psm1
Set-StrictMode -Version 3 Import-Module "$PSScriptRoot\WinGet-Utils.psm1" [string]$PackageDatabase = "$PSScriptRoot\winget.packages.json" [string]$IgnoreFilePath = "$PSScriptRoot\winget.{HOSTNAME}.ignore" <# .DESCRIPTION This is the back end handler for initializing various user-facing files that typically are expected to resize external to the module install location but symlinked. #> function Initialize-WinGetResource { param( # The path to an existing file. This file will be symbolically linked. [string]$SourceFile, # Points to one of the internally referernced resource files which # the -SourceFile will be SymLink'd or copied to. [string]$DestinationFile ) $DestinationFilename = $(Split-Path -Leaf $DestinationFile) if (-not([string]::IsNullOrWhiteSpace($SourceFile))) { if ((Test-Path $DestinationFile) -and -not(Test-ReparsePoint $DestinationFile)) { Write-Output "Backing up existing '$DestinationFilename'." Move-Item $DestinationFile -Destination "$DestinationFile.bak" -Force } $SymLinkArgs = @{ ItemType = "SymbolicLink" Path = "$(Split-Path -Parent $DestinationFile)" Name = $DestinationFilename Value = "$($SourceFile | Resolve-Path)" Force = $true } Write-Output "Creating new symlink for '$DestinationFilename'." New-Item @SymLinkArgs } elseif (Test-Path $DestinationFile) { Write-Output "The '$DestinationFilename' file is already initialized." return } else { $currentVersion = [version]"0.0" if (-not[version]::TryParse((Split-Path -Leaf (Get-Item $PSScriptRoot/..)), [ref]$currentVersion)) { # Not installed as a module, do not try to migrate Write-Output "Not installed as a module. Migration of '$DestinationFilename' cannot be performed." return } $selectedVersion = [version]"0.0" $selectedPackageFile = $null $moduleVersionPaths = Get-ChildItem -Directory $PSScriptRoot/../.. $moduleVersionPaths | Where-Object { [version]($_.Name) -ne $currentVersion } | ForEach-Object { $packageFile = (Join-Path $_ "modules/$DestinationFilename") if (Test-Path $packageFile) { $version = [version](Split-Path -Leaf $_) if ($version -gt $selectedVersion) { $selectedVersion = $version $selectedPackageFile = $packageFile } } } if ($null -ne $selectedPackageFile) { $source = Get-Item $selectedPackageFile if ($source.Target) { if (-not(Test-Administrator)) { Write-Warning "A symlink to '$DestinationFilename' cannot be created as a non-admin." return } Write-Output "Creating new symlink to '$DestinationFilename'." $SymLinkArgs = @{ ItemType = "SymbolicLink" Path = "$(Split-Path -Parent $DestinationFile)" Name = $DestinationFilename Value = $source.Target } New-Item @SymLinkArgs } else { Write-Output "Copying existing '$DestinationFilename'." Copy-Item -Path $source.FullName -Destination $DestinationFile } } else { Write-Output "No '$DestinationFilename' detected." Write-Output "Create one and provide it as the argument to -SourceFile." } } } <# .DESCRIPTION Initialize the local "winget.software.json" needed by Restore-WinGetSoftware. If -SourceFile is specified, the file will be symbolically linked to the appropriate location. When this parameter is not specified, the cmdlet will auto-detect other installed module versions and attempt to find the latest existing "winget.packages.json". In such cases, it will make a symlink only if one was used previously; otherwise it will copy the previous file. .EXAMPLE PS> Initialize-WinGetRestore -SourceFile "./winget.software.json" .EXAMPLE PS> Initialize-WinGetRestore #> function Initialize-WinGetRestore { param( <# The path to an existing "winget.software.json" file. This file will be symbolically linked. #> [string]$SourceFile, <# When set, the cmdlet will automatically relaunch using an Administrator PowerShell instance. This cmdlet needs such permissions to create Symbolic Links. #> [switch]$Administrator ) if ($Administrator -and -not(Test-Administrator)) { $boundParamsString = $PSBoundParameters.Keys | ForEach-Object { if ($PSBoundParameters[$_] -is [switch]) { if ($PSBoundParameters[$_]) { "-$($_)" } } else { "-$($_) $($PSBoundParameters[$_])" } } $cmdArgs = "-NoLogo -NoExit -Command Initialize-WinGetRestore $($boundParamsString -join ' ')" Start-Process -Verb RunAs -FilePath "pwsh" -ArgumentList $cmdArgs return } Initialize-WinGetResource -SourceFile $SourceFile -DestinationFile $PackageDatabase } <# .DESCRIPTION Initialize the local "winget.{HOSTNAME}.ignore" used by various cmdlets. If -SourceFile is specified, the file will be symbolically linked to the appropriate location. When this parameter is not specified, the cmdlet will auto-detect other installed module versions and attempt to find the latest existing "winget.{HOSTNAME}.ignore". In such cases, it will make a symlink only if one was used previously; otherwise it will copy the previous file. .EXAMPLE PS> Initialize-WinGetIgnore -SourceFile "./winget.example-hostname.ignore" .EXAMPLE PS> Initialize-WinGetIgnore #> function Initialize-WinGetIgnore { param( <# The path to an existing winget-ignore file. This file will be symbolically linked. #> [string]$SourceFile, <# When set, the cmdlet will automatically relaunch using an Administrator PowerShell instance. This cmdlet needs such permissions to create Symbolic Links. #> [switch]$Administrator ) if ($Administrator -and -not(Test-Administrator)) { $boundParamsString = $PSBoundParameters.Keys | ForEach-Object { if ($PSBoundParameters[$_] -is [switch]) { if ($PSBoundParameters[$_]) { "-$($_)" } } else { "-$($_) $($PSBoundParameters[$_])" } } $cmdArgs = "-NoLogo -NoExit -Command Initialize-WinGetIgnore $($boundParamsString -join ' ')" Start-Process -Verb RunAs -FilePath "pwsh" -ArgumentList $cmdArgs return } $ignoreFile = $IgnoreFilePath.Replace('{HOSTNAME}', $(hostname).ToLower()) Initialize-WinGetResource -SourceFile $SourceFile -DestinationFile $ignoreFile } |