Skip to content

Commit

Permalink
Add command not found (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasNieto authored Aug 15, 2024
1 parent 46bcbc3 commit 8bd7f7c
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 51 deletions.
6 changes: 3 additions & 3 deletions src/AnyPackage.Scoop.psd1
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
@{
RootModule = 'AnyPackage.Scoop.psm1'
ModuleVersion = '0.1.4'
ModuleVersion = '0.2.0'
CompatiblePSEditions = @('Desktop', 'Core')
GUID = 'bc4720f6-72ad-45df-aa7d-316cb313ad5e'
Author = 'Thomas Nieto'
Copyright = '(c) 2023 Thomas Nieto. All rights reserved.'
Description = 'Scoop provider for AnyPackage.'
PowerShellVersion = '5.1'
RequiredModules = @(
@{ ModuleName = 'AnyPackage'; ModuleVersion = '0.5.1' },
@{ ModuleName = 'Scoop'; ModuleVersion = '0.1.1' })
@{ ModuleName = 'AnyPackage'; ModuleVersion = '0.6.0' },
@{ ModuleName = 'Scoop'; ModuleVersion = '0.2.0' })
FunctionsToExport = @()
CmdletsToExport = @()
AliasesToExport = @()
Expand Down
137 changes: 89 additions & 48 deletions src/AnyPackage.Scoop.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,44 @@
# terms of the MIT license.

using module AnyPackage
using module Scoop
using namespace AnyPackage.Provider
using namespace NuGet.Versioning
using namespace AnyPackage.Feedback
using namespace System.Collections.Generic
using namespace System.IO
using namespace System.Management.Automation
using namespace System.Threading

[PackageProvider('Scoop')]
class ScoopProvider : PackageProvider, IFindPackage, IGetPackage,
IInstallPackage, IUpdatePackage, IUninstallPackage, IGetSource, ISetSource {
IInstallPackage, IUpdatePackage, IUninstallPackage, IGetSource, ISetSource, ICommandNotFound {
[PackageProviderInfo] Initialize([PackageProviderInfo] $providerInfo) {
return [ScoopProviderInfo]::new($providerInfo)
}

[IEnumerable[CommandNotFoundFeedback]] FindPackage([CommandNotFoundContext] $context, [CancellationToken] $token) {
$dict = [Dictionary[string, CommandNotFoundFeedback]]::new([StringComparer]::OrdinalIgnoreCase)
$key = [Path]::GetFileNameWithoutExtension($context.Command)
$packages = $this.ProviderInfo.CommandCache[$key]

foreach ($package in $packages) {
if (!$dict.ContainsKey($package.Name) -and $package.Binaries -match $context.Command) {
$feedback = [CommandNotFoundFeedback]::new($package.Name, $this.ProviderInfo)
$dict.Add($package.Name, $feedback)
}
}

return $dict.Values
}

[void] FindPackage([PackageRequest] $request) {
Find-ScoopApp -Name $request.Name |
Write-Package -Request $request -OfficialSources $this.ProviderInfo.OfficialSources
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
Write-Package -Request $request -OfficialSources $this.ProviderInfo.OfficialSources
}

[void] InstallPackage([PackageRequest] $request) {
Expand Down Expand Up @@ -52,12 +71,12 @@ class ScoopProvider : PackageProvider, IFindPackage, IGetPackage,
if ($request.Source) { $findPackageParameters['Bucket'] = $request.Source }

Find-ScoopApp @findPackageParameters |
Where-Object { $request.IsMatch([PackageVersion]$_.Version) } |
Select-Object -Property Name |
Install-ScoopApp @installScoopAppParams
Where-Object { $request.IsMatch([PackageVersion]$_.Version) } |
Select-Object -Property Name |
Install-ScoopApp @installScoopAppParams

Get-ScoopApp -Name $request.Name |
Write-Package -Request $request -OfficialSources $this.ProviderInfo.OfficialSources
Write-Package -Request $request -OfficialSources $this.ProviderInfo.OfficialSources
}

[void] UpdatePackage([PackageRequest] $request) {
Expand All @@ -83,19 +102,19 @@ class ScoopProvider : PackageProvider, IFindPackage, IGetPackage,
$installScoopAppParams['Force'] = $true
}

$getPackageParameters = @{ Name = $request.Name}
$getPackageParameters = @{ Name = $request.Name }
$findPackageParameters = @{ }

if ($request.Source) { $findPackageParameters['Bucket'] = $request.Source }

Get-ScoopApp @getPackageParameters |
Find-ScoopApp @findPackageParameters |
Where-Object { $request.IsMatch([PackageVersion]$_.Version) } |
Select-Object -Property Name |
Update-ScoopApp @installScoopAppParams
Find-ScoopApp @findPackageParameters |
Where-Object { $request.IsMatch([PackageVersion]$_.Version) } |
Select-Object -Property Name |
Update-ScoopApp @installScoopAppParams

Get-ScoopApp -Name $request.Name |
Write-Package -Request $request -OfficialSources $this.ProviderInfo.OfficialSources
Write-Package -Request $request -OfficialSources $this.ProviderInfo.OfficialSources
}

[void] UninstallPackage([PackageRequest] $request) {
Expand All @@ -110,19 +129,19 @@ class ScoopProvider : PackageProvider, IFindPackage, IGetPackage,
}

$package = Get-ScoopApp -Name $request.Name |
Where-Object { $request.IsMatch([PackageVersion]$_.Version) }
Where-Object { $request.IsMatch([PackageVersion]$_.Version) }

$package | Uninstall-ScoopApp @uninstallScoopAppParams

if (-not ($package | Get-ScoopApp)) {
$package |
Write-Package -Request $request -OfficialSources $this.PackageInfo.OfficialSources
Write-Package -Request $request -OfficialSources $this.PackageInfo.OfficialSources
}
}

[void] GetSource([SourceRequest] $sourceRequest) {
Get-ScoopBucket |
Write-Source -Request $sourceRequest -OfficialSources $this.ProviderInfo.OfficialSources
Write-Source -Request $sourceRequest -OfficialSources $this.ProviderInfo.OfficialSources
}

[void] RegisterSource([SourceRequest] $sourceRequest) {
Expand All @@ -138,8 +157,7 @@ class ScoopProvider : PackageProvider, IFindPackage, IGetPackage,
$name = $sourceRequest.Name
$registerBucketParams['Name'] = $sourceRequest.Name
$registerBucketParams['Uri'] = $sourceRequest.Location
}
else {
} else {
if (-not ($sourceRequest.DynamicParameters.Official -in $this.ProviderInfo.OfficialSources.Keys)) {
throw "'$($sourceRequest.DynamicParameters.Official)' is not an official source."
}
Expand All @@ -155,7 +173,7 @@ class ScoopProvider : PackageProvider, IFindPackage, IGetPackage,
Register-ScoopBucket @registerBucketParams

Get-ScoopBucket -Name $name |
Write-Source -Request $sourceRequest -OfficialSources $this.ProviderInfo.OfficialSources
Write-Source -Request $sourceRequest -OfficialSources $this.ProviderInfo.OfficialSources
}

[void] SetSource([SourceRequest] $sourceRequest) {
Expand All @@ -176,17 +194,17 @@ class ScoopProvider : PackageProvider, IFindPackage, IGetPackage,
Unregister-ScoopBucket -Name $sourceRequest.Name

$source |
Write-Source -Request $sourceRequest -OfficialSources $this.ProviderInfo.OfficialSources
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 }
})
'Register-PackageSource' { [RegisterPackageSourceDynamicParameters]::new() }
'Install-Package' { [InstallPackageDynamicParameters]::new() }
'Uninstall-Package' { [UninstallPackageDynamicParameters]::new() }
'Update-Package' { [UpdatePackageDynamicParameters]::new() }
default { $null }
})
}
}

Expand Down Expand Up @@ -240,24 +258,30 @@ class UninstallPackageDynamicParameters : ScopeDynamicParameters {

class ScoopProviderInfo : PackageProviderInfo {
[hashtable] $OfficialSources
[Dictionary[string, List[ScoopAppDetailed]]] $CommandCache = [Dictionary[string, List[ScoopAppDetailed]]]::new([StringComparer]::OrdinalIgnoreCase)


ScoopProviderInfo([PackageProviderInfo] $providerInfo) : base($providerInfo) {
$this.SetOfficialSources()

if ([Runspace]::DefaultRunspace.Name -eq $this.FullName) {
$this.SetCommandCache()
}
}

hidden [void] SetOfficialSources() {
[void] SetOfficialSources() {
$path = Get-Command -Name Scoop |
Select-Object -ExpandProperty Path |
Split-Path |
Split-Path |
Join-Path -ChildPath apps\scoop\current\buckets.json
Select-Object -ExpandProperty Path |
Split-Path |
Split-Path |
Join-Path -ChildPath apps\scoop\current\buckets.json

$sources = Get-Content -Path $path |
ConvertFrom-Json
ConvertFrom-Json

$keys = $sources |
Get-Member -MemberType NoteProperty |
Select-Object -ExpandProperty Name
Get-Member -MemberType NoteProperty |
Select-Object -ExpandProperty Name

$ht = @{ }
foreach ($key in $keys) {
Expand All @@ -266,6 +290,24 @@ class ScoopProviderInfo : PackageProviderInfo {

$this.OfficialSources = $ht
}

[void] SetCommandCache() {
$packages = Find-ScoopApp

foreach ($package in $packages) {
foreach ($command in $package.Binaries) {
$key = [Path]::GetFileNameWithoutExtension($command)

if ($this.CommandCache.ContainsKey($key)) {
$this.CommandCache[$key] += $package
} else {
$list = [List[ScoopAppDetailed]]::new()
$list += $package
$this.CommandCache.Add($key, $package)
}
}
}
}
}

$ScriptBlock = {
Expand All @@ -275,12 +317,12 @@ $ScriptBlock = {
$null = $commandName, $parameterName, $commandAst, $fakeBoundParameters

Get-PackageProvider -Name Scoop |
Select-Object -ExpandProperty OfficialSources |
Select-Object -ExpandProperty Keys |
Where-Object Name -Like "$wordToComplete*" |
ForEach-Object {
[CompletionResult]::new($_)
}
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
Expand Down Expand Up @@ -378,15 +420,14 @@ function Write-Package {

if ($Source -eq '<auto-generated>' -or (Test-Path -Path $Source)) {
$sourceInfo = $null
}
else {
$bucket = $buckets | Where-Object Name -eq $Source
} else {
$bucket = $buckets | Where-Object Name -EQ $Source
$trusted = if ($bucket.Source -in $OfficialSources.Values) { $true } else { $false }
$sourceInfo = [PackageSourceInfo]::new($bucket.Name,
$bucket.Source,
$trusted,
@{ Updated = $bucket.Updated; Manifests = $bucket.Manifests },
$Request.ProviderInfo)
$bucket.Source,
$trusted,
@{ Updated = $bucket.Updated; Manifests = $bucket.Manifests },
$Request.ProviderInfo)
}

if ($Request.IsMatch($Name, $Version)) {
Expand Down

0 comments on commit 8bd7f7c

Please sign in to comment.