AnyPackage.Scoop.psm1
# Copyright (c) Thomas Nieto - All Rights Reserved # You may use, distribute and modify this code under the # terms of the MIT license. using module AnyPackage using namespace AnyPackage.Provider using namespace NuGet.Versioning using namespace System.Management.Automation [PackageProvider('Scoop')] class ScoopProvider : PackageProvider, IFindPackage, IGetPackage, IInstallPackage, IUpdatePackage, IUninstallPackage, IGetSource, ISetSource { ScoopProvider() : base('28111522-ea7a-4e8a-b598-85389c17f8be') { } [PackageProviderInfo] Initialize([PackageProviderInfo] $providerInfo) { return [ScoopProviderInfo]::new($providerInfo) } [void] FindPackage([PackageRequest] $request) { Find-ScoopApp -Name $request.Name | Write-Package -Request $request -OfficialSources $this.ProviderInfo.OfficialSources } [void] GetPackage([PackageRequest] $request) { Get-ScoopApp -Name $request.Name | Write-Package -Request $request -OfficialSources $this.ProviderInfo.OfficialSources } [void] InstallPackage([PackageRequest] $request) { $installScoopAppParams = @{ } if ($request.DynamicParameters.Architecture) { $installScoopAppParams['Architecture'] = $request.DynamicParameters.Architecture } if ($request.DynamicParameters.SkipDependencies) { $installScoopAppParams['SkipDependencies'] = $request.DynamicParameters.SkipDependencies } if ($request.DynamicParameters.NoCache) { $installScoopAppParams['NoCache'] = $request.DynamicParameters.NoCache } if ($request.DynamicParameters.SkipHashCheck) { $installScoopAppParams['SkipHashCheck'] = $request.DynamicParameters.SkipHashCheck } if ($request.DynamicParameters.Scope -eq 'AllUsers') { $installScoopAppParams['Global'] = $true } $findPackageParameters = @{ Name = $request.Name } if ($request.Source) { $findPackageParameters['Bucket'] = $request.Source } Find-ScoopApp @findPackageParameters | Where-Object { try { $request.IsMatch([NuGetVersion]$_.Version) } catch { $request.IsMatch([NuGetVersion]'0.0.0') } } | Select-Object -Property Name | Install-ScoopApp @installScoopAppParams Get-ScoopApp -Name $request.Name | Write-Package -Request $request -OfficialSources $this.ProviderInfo.OfficialSources } [void] UpdatePackage([PackageRequest] $request) { $installScoopAppParams = @{ } if ($request.DynamicParameters.SkipDependencies) { $installScoopAppParams['SkipDependencies'] = $request.DynamicParameters.SkipDependencies } if ($request.DynamicParameters.NoCache) { $installScoopAppParams['NoCache'] = $request.DynamicParameters.NoCache } if ($request.DynamicParameters.SkipHashCheck) { $installScoopAppParams['SkipHashCheck'] = $request.DynamicParameters.SkipHashCheck } if ($request.DynamicParameters.Scope -eq 'AllUsers') { $installScoopAppParams['Global'] = $true } if ($request.DynamicParameters.Reinstall) { $installScoopAppParams['Force'] = $true } $getPackageParameters = @{ Name = $request.Name} $findPackageParameters = @{ } if ($request.Source) { $findPackageParameters['Bucket'] = $request.Source } Get-ScoopApp @getPackageParameters | Find-ScoopApp @findPackageParameters | Where-Object { try { $request.IsMatch([NuGetVersion]$_.Version) } catch { $request.IsMatch([NuGetVersion]'0.0.0') } } | Select-Object -Property Name | Update-ScoopApp @installScoopAppParams Get-ScoopApp -Name $request.Name | Write-Package -Request $request -OfficialSources $this.ProviderInfo.OfficialSources } [void] UninstallPackage([PackageRequest] $request) { $uninstallScoopAppParams = @{ } if ($request.DynamicParameters.RemoveData) { $uninstallScoopAppParams['Purge'] = $request.DynamicParameters.RemoveData } if ($request.DynamicParameters.Scope -eq 'AllUsers') { $uninstallScoopAppParams['Global'] = $true } $package = Get-ScoopApp -Name $request.Name | Where-Object { try { $request.IsMatch([NuGetVersion]$_.Version) } catch { $request.IsMatch([NuGetVersion]'0.0.0') } } $package | Uninstall-ScoopApp @uninstallScoopAppParams if (-not ($package | Get-ScoopApp)) { $package | Write-Package -Request $request -OfficialSources $this.PackageInfo.OfficialSources } } [void] GetSource([SourceRequest] $sourceRequest) { Get-ScoopBucket | Write-Source -Request $sourceRequest -OfficialSources $this.ProviderInfo.OfficialSources } [void] RegisterSource([SourceRequest] $sourceRequest) { if ($sourceRequest.Trusted) { throw 'Scoop provider does not support Trusted parameter.' } $registerBucketParams = @{ Force = $sourceRequest.Force } if ($sourceRequest.Name) { $name = $sourceRequest.Name $registerBucketParams['Name'] = $sourceRequest.Name $registerBucketParams['Uri'] = $sourceRequest.Location } else { if (-not ($sourceRequest.DynamicParameters.Official -in $this.ProviderInfo.OfficialSources.Keys)) { throw "'$($sourceRequest.DynamicParameters.Official)' is not an official source." } $name = $sourceRequest.DynamicParameters.Official $registerBucketParams['Official'] = $sourceRequest.DynamicParameters.Official } if ((Get-ScoopBucket -Name $name) -and -not $sourceRequest.Force) { throw "Source '$name' already exists. Use -Force to recreate the source." } Register-ScoopBucket @registerBucketParams Get-ScoopBucket -Name $name | Write-Source -Request $sourceRequest -OfficialSources $this.ProviderInfo.OfficialSources } [void] SetSource([SourceRequest] $sourceRequest) { if ($sourceRequest.Trusted) { throw 'Scoop provider does not support Trusted parameter.' } Register-ScoopBucket -Name $sourceRequest.Name -Uri $sourceRequest.Location -Force $this.GetSource($sourceRequest) } [void] UnregisterSource([SourceRequest] $sourceRequest) { $source = Get-ScoopBucket -Name $sourceRequest.Name if (-not $source) { return } Unregister-ScoopBucket -Name $sourceRequest.Name $source | Write-Source -Request $sourceRequest -OfficialSources $this.ProviderInfo.OfficialSources } [object] GetDynamicParameters([string] $commandName) { return $(switch ($commandName) { 'Register-PackageSource' { [RegisterPackageSourceDynamicParameters]::new() } 'Install-Package' { [InstallPackageDynamicParameters]::new() } 'Uninstall-Package' { [UninstallPackageDynamicParameters]::new() } 'Update-Package' { [UpdatePackageDynamicParameters]::new() } default { $null } }) } } class RegisterPackageSourceDynamicParameters { [Parameter(Mandatory, ParameterSetName = 'Official')] [ValidateNotNullOrEmpty()] [string] $Official } class ScopeDynamicParameters { [Parameter()] [ValidateSet('CurrentUser', 'AllUsers')] [string] $Scope = 'CurrentUser' } class OptionalDynamicParameters : ScopeDynamicParameters { [Parameter()] [switch] $SkipDependencies [Parameter()] [switch] $NoCache [Parameter()] [switch] $SkipHashCheck } class InstallPackageDynamicParameters : OptionalDynamicParameters { [Parameter()] [ValidateSet('32bit', '64bit', 'arm64')] [string] $Architecture } class UpdatePackageDynamicParameters : OptionalDynamicParameters { [Parameter()] [switch] $Reinstall } class UninstallPackageDynamicParameters : ScopeDynamicParameters { [Parameter()] [switch] $RemoveData } class ScoopProviderInfo : PackageProviderInfo { [hashtable] $OfficialSources ScoopProviderInfo([PackageProviderInfo] $providerInfo) : base($providerInfo) { $this.SetOfficialSources() } hidden [void] SetOfficialSources() { $path = Get-Command -Name Scoop | Select-Object -ExpandProperty Path | Split-Path | Split-Path | Join-Path -ChildPath apps\scoop\current\buckets.json $sources = Get-Content -Path $path | ConvertFrom-Json $keys = $sources | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name $ht = @{ } foreach ($key in $keys) { $ht[$key] = $sources.$key } $this.OfficialSources = $ht } } $ScriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) Get-PackageProvider -Name Scoop | Select-Object -ExpandProperty OfficialSources | Select-Object -ExpandProperty Keys | Where-Object Name -Like "$wordToComplete*" | ForEach-Object { [CompletionResult]::new($_) } } Register-ArgumentCompleter -CommandName Register-PackageSource -ParameterName Official -ScriptBlock $ScriptBlock [PackageProviderManager]::RegisterProvider([ScoopProvider], $MyInvocation.MyCommand.ScriptBlock.Module) $MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = { [PackageProviderManager]::UnregisterProvider([ScoopProvider]) } function Write-Source { [CmdletBinding()] param ( [Parameter(ValueFromPipelineByPropertyName)] [string] $Name, [Parameter(ValueFromPipelineByPropertyName)] [Alias('Source')] [string] $Location, [Parameter(ValueFromPipelineByPropertyName)] [datetime] $Updated, [Parameter(ValueFromPipelineByPropertyName)] [int] $Manifests, [Parameter(Mandatory)] [SourceRequest] $Request, [Parameter()] [hashtable] $OfficialSources ) process { if ($Name -like $Request.Name) { $trusted = if ($Location -in $OfficialSources.Values) { $true } else { $false } $Request.WriteSource($Name, $Location, $trusted, @{Updated = $_.Updated; Manifests = $_.Manifests }) } } } function Write-Package { [CmdletBinding()] param ( [Parameter(ValueFromPipelineByPropertyName)] [string] $Name, [Parameter(ValueFromPipelineByPropertyName)] [string] $Version, [Parameter(ValueFromPipelineByPropertyName)] [string] $Description, [Parameter(ValueFromPipelineByPropertyName)] [string] $Source, [Parameter(ValueFromPipelineByPropertyName)] [datetime] $Updated, [Parameter(ValueFromPipelineByPropertyName)] [string] $Info, [Parameter(Mandatory)] [PackageRequest] $Request, [Parameter()] [object[]] $Sources, [Parameter()] [hashtable] $OfficialSources ) begin { $buckets = Get-ScoopBucket } process { $metadata = @{ } if ($Updated) { $metadata['Updated'] = $Updated } if ($Info) { $metadata['Info'] = $Info } if ($Request.Source -and $Source -ne $Request.Source) { return } if ($Source -eq '<auto-generated>' -or (Test-Path -Path $Source)) { $sourceInfo = $null } else { $bucket = $buckets | Where-Object Name -eq $Source $trusted = if ($bucket.Source -in $OfficialSources.Values) { $true } else { $false } $sourceInfo = $Request.NewSourceInfo($bucket.Name, $bucket.Source, $trusted, @{Updated = $_.Updated; Manifests = $_.Manifests }) } try { [NuGetVersion]::Parse($Version) } catch { $request.WriteWarning("Package '$Name' has an invalid version '$Version'. Changing version to '0.0.0'.") $Version = '0.0.0' } if ($Request.IsMatch($Name, $Version)) { $Request.WritePackage($Name, $Version, $Description, $sourceInfo, $metadata) } } } |