Skip to content

Commit

Permalink
Crescendo refactor (#23)
Browse files Browse the repository at this point in the history
Changed
* ChocolateyGet CLI integration with Choco.exe is now based on the [Foil](https://github.com/ethanbergstrom/Foil) PowerShell Crescendo module

Removed
* The AdditionalArgs parameter will now only pass package argument/parameter-related values to Choco.exe
* The dependency on Foil (and Crescendo) means ChocolateyGet is no longer supported with PowerShell 5.0 and below
  • Loading branch information
ethanbergstrom authored Mar 28, 2021
1 parent c574b2f commit 7fc241b
Show file tree
Hide file tree
Showing 19 changed files with 435 additions and 421 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.0.0] - 2021-03-28
#### Changed
* ChocolateyGet CLI integration with Choco.exe is now based on the [Foil](https://github.com/ethanbergstrom/Foil) PowerShell Crescendo module
#### Removed
* The AdditionalArgs parameter will now only pass package argument/parameter-related values to Choco.exe
* The dependency on Foil (and Crescendo) means ChocolateyGet is no longer supported with PowerShell 5.0 and below

## [2.1.0] - 2021-01-23
#### Changed
* Change default search to use exact package name if both package name and required version are specified (#20)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ ChocolateyGet integrates with Choco.exe to manage and store source information
If you need to pass in some of choco arguments to the Find, Install, Get and Uninstall-Package cmdlets, you can use AdditionalArguments PowerShell property.

```powershell
Install-Package sysinternals -Provider ChocolateyGet -AcceptLicense -AdditionalArguments '--paramsglobal --params "/InstallDir=c:\windows\temp\sysinternals /QuickLaunchShortcut=false" -y --installargs MaintenanceService=false' -Verbose
Install-Package sysinternals -Provider ChocolateyGet -AcceptLicense -AdditionalArguments '--paramsglobal --params "/InstallDir:c:\windows\temp\sysinternals /QuickLaunchShortcut:false" -y --installargs MaintenanceService=false' -Verbose
```

## DSC Compatibility
Expand Down
71 changes: 44 additions & 27 deletions Test/ChocolateyGet.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,15 @@ Describe "$platform basic package search operations" {
}
}
Context 'with additional arguments' {
$package = 'cpu-z'
$argsAndParams = '--exact'
BeforeAll {
$package = 'sysinternals'
$installDir = Join-Path -Path $env:ProgramFiles -ChildPath $package
$params = "--paramsglobal --params ""/InstallDir:$installDir /QuickLaunchShortcut:false"""
Remove-Item -Force -Recurse -Path $installDir -ErrorAction SilentlyContinue
}

It 'searches for the exact package name' {
Find-Package -Provider $ChocolateyGet -Name $package -AdditionalArguments $argsAndParams | Should -Not -BeNullOrEmpty
Find-Package -Provider $ChocolateyGet -Name $package -AdditionalArguments $params | Should -Not -BeNullOrEmpty
}
}
}
Expand All @@ -52,21 +56,28 @@ Describe "$platform DSC-compliant package installation and uninstallation" {
Uninstall-Package -Provider $ChocolateyGet -Name $package | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
}
}
Context 'with additional arguments' {
$package = 'sysinternals'
$argsAndParams = '--paramsglobal --params "/InstallDir='+$env:TEMP+'\sysinternals /QuickLaunchShortcut=false" -y --installargs MaintenanceService=false'
Context 'with additional parameters' {
BeforeAll {
$package = 'sysinternals'
$installDir = Join-Path -Path $env:ProgramFiles -ChildPath $package
$params = "--paramsglobal --params ""/InstallDir:$installDir /QuickLaunchShortcut:false"""
Remove-Item -Force -Recurse -Path $installDir -ErrorAction SilentlyContinue
}

It 'searches for the latest version of a package' {
Find-Package -Provider $ChocolateyGet -Name $package -AdditionalArguments $argsAndParams | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
Find-Package -Provider $ChocolateyGet -Name $package -AdditionalArguments $params | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
}
It 'silently installs the latest version of a package' {
Install-Package -Force -Provider $ChocolateyGet -Name $package -AdditionalArguments $argsAndParams | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
Install-Package -Force -Provider $ChocolateyGet -Name $package -AdditionalArguments $params | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
}
It 'correctly passed parameters to the package' {
Get-ChildItem -Path $installDir -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
It 'finds the locally installed package just installed' {
Get-Package -Provider $ChocolateyGet -Name $package -AdditionalArguments $argsAndParams | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
Get-Package -Provider $ChocolateyGet -Name $package -AdditionalArguments $params | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
}
It 'silently uninstalls the locally installed package just installed' {
Uninstall-Package -Provider $ChocolateyGet -Name $package -AdditionalArguments $argsAndParams | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
Uninstall-Package -Provider $ChocolateyGet -Name $package -AdditionalArguments $params | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
}
}
}
Expand All @@ -82,49 +93,55 @@ Describe "$platform pipline-based package installation and uninstallation" {
Get-Package -Provider $ChocolateyGet -Name $package | Uninstall-Package | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
}
}
Context 'with additional arguments' {
$package = 'sysinternals'
$argsAndParams = '--paramsglobal --params "/InstallDir='+$env:TEMP+'\sysinternals /QuickLaunchShortcut=false" -y --installargs MaintenanceService=false'
Context 'with additional parameters' {
BeforeAll {
$package = 'sysinternals'
$installDir = Join-Path -Path $env:ProgramFiles -ChildPath $package
$params = "--paramsglobal --params ""/InstallDir:$installDir /QuickLaunchShortcut:false"""
Remove-Item -Force -Recurse -Path $installDir -ErrorAction SilentlyContinue
}

It 'searches for and silently installs the latest version of a package' {
Find-Package -Provider $ChocolateyGet -Name $package | Install-Package -Force -AdditionalArguments $argsAndParams | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
Find-Package -Provider $ChocolateyGet -Name $package | Install-Package -Force -AdditionalArguments $params | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
}
It 'correctly passed parameters to the package' {
Get-ChildItem -Path $installDir -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}

It 'finds and silently uninstalls the locally installed package just installed' {
Get-Package -Provider $ChocolateyGet -Name $package | Uninstall-Package -AdditionalArguments $argsAndParams | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
Get-Package -Provider $ChocolateyGet -Name $package | Uninstall-Package -AdditionalArguments $params | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
}
}
}

Describe "$platform multi-source support" {
BeforeAll {
$altSourceName = 'LocalChocoSource'
$altSourceLocation = $PSScriptRoot
$altSource = 'LocalChocoSource'
$altLocation = $PSScriptRoot
$package = 'cpu-z'

Save-Package $package -Source 'http://chocolatey.org/api/v2' -Path $altSourceLocation
Unregister-PackageSource -Name $altSourceName -Provider $ChocolateyGet -ErrorAction SilentlyContinue
Save-Package $package -Source 'http://chocolatey.org/api/v2' -Path $altLocation
Unregister-PackageSource -Name $altSource -Provider $ChocolateyGet -ErrorAction SilentlyContinue
}
AfterAll {
Remove-Item "$altSourceLocation\*.nupkg" -Force -ErrorAction SilentlyContinue
Unregister-PackageSource -Name $altSourceName -Provider $ChocolateyGet -ErrorAction SilentlyContinue
Remove-Item "$altLocation\*.nupkg" -Force -ErrorAction SilentlyContinue
Unregister-PackageSource -Name $altSource -Provider $ChocolateyGet -ErrorAction SilentlyContinue
}

It 'refuses to register a source with no location' {
Register-PackageSource -Name $altSourceName -Provider $ChocolateyGet -ErrorAction SilentlyContinue | Where-Object {$_.Name -eq $altSourceName} | Should -BeNullOrEmpty
Register-PackageSource -Name $altSource -Provider $ChocolateyGet -ErrorAction SilentlyContinue | Where-Object {$_.Name -eq $altSource} | Should -BeNullOrEmpty
}
It 'registers an alternative package source' {
Register-PackageSource -Name $altSourceName -Provider $ChocolateyGet -Location $altSourceLocation | Where-Object {$_.Name -eq $altSourceName} | Should -Not -BeNullOrEmpty
Register-PackageSource -Name $altSource -Provider $ChocolateyGet -Location $altLocation | Where-Object {$_.Name -eq $altSource} | Should -Not -BeNullOrEmpty
}
It 'searches for and installs the latest version of a package from an alternate source' {
Find-Package -Provider $ChocolateyGet -Name $package -source $altSourceName | Install-Package -Force | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
Find-Package -Provider $ChocolateyGet -Name $package -source $altSource | Install-Package -Force | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
}
It 'finds and uninstalls a package installed from an alternate source' {
Get-Package -Provider $ChocolateyGet -Name $package | Uninstall-Package | Where-Object {$_.Name -contains $package} | Should -Not -BeNullOrEmpty
}
It 'unregisters an alternative package source' {
Unregister-PackageSource -Name $altSourceName -Provider $ChocolateyGet
Get-PackageSource -Provider $ChocolateyGet | Where-Object {$_.Name -eq $altSourceName} | Should -BeNullOrEmpty
Unregister-PackageSource -Name $altSource -Provider $ChocolateyGet
Get-PackageSource -Provider $ChocolateyGet | Where-Object {$_.Name -eq $altSource} | Should -BeNullOrEmpty
}
}

Expand Down
3 changes: 2 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ install:

build_script:
- ps: |
Install-Module -Name Foil -Force
New-Item -ItemType Directory -Name lib -Path ~\Documents\WindowsPowerShell\Modules\ChocolateyGet\
Copy-Item .\src\* ~\Documents\WindowsPowerShell\Modules\ChocolateyGet\ -Recurse
Copy-Item .\packages\chocolatey.lib\lib\chocolatey.dll ~\Documents\WindowsPowerShell\Modules\ChocolateyGet\lib\ -Force
Expand All @@ -21,5 +22,5 @@ test_script:
- pwsh: Invoke-Pester -EnableExit -OutputFormat NUnitXml -OutputFile TestsResults.CLI.xml
- pwsh: (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\TestsResults.CLI.xml))

after_build:
on_finish:
- ps: Get-ChildItem $env:programdata\chocolatey\logs | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
8 changes: 4 additions & 4 deletions src/ChocolateyGet.Resource.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ ConvertFrom-StringData @'
UserDeclined=User declined to {0} Chocolatey.
NotInstalled=Package '{0}' is not installed.
FailToInstall=Failed to install the package because the fast reference '{0}' is incorrect.
FailToUninstall=Failed to uninstall the package because the fast reference '{0}' is incorrect.
FailToInstall=Failed to install the package because the package reference '{0}' is incorrect.
FailToUninstall=Failed to uninstall the package because the package reference '{0}' is incorrect.
FailToInstallChoco=choco installed failed. You may relaunch PowerShell as elevated mode and try again.
UnexpectedChocoResponse=Successful output from choco.exe for fast reference '{0}' did not match the exepected format. Please review Chocolatey logs for more information.
UnexpectedChocoResponse=Output from choco.exe for package reference '{0}' did not match the exepected format. Please review Chocolatey logs for more information.
InstallPackageQuery={0} package '{1}'. By {0} you accept licenses for the package(s). The package possibly needs to run 'chocolateyInstall.ps1'.
InstallPackageCaption=Are you sure you want to perform this action?
Expand All @@ -23,7 +23,7 @@ ConvertFrom-StringData @'
MinimumVersionIsGreaterThanMaximumVersion=The specified MinimumVersion '{0}' is greater than the specified MaximumVersion '{1}'.
VersionParametersAreAllowedOnlyWithSingleName=The RequiredVersion, MinimumVersion, MaximumVersion or AllVersions parameters are allowed only when you specify a single name as the value of the Name parameter, without any wildcard characters.
SpecifiedSourceName=Using the specified source names: '{0}'.
SpecifiedSource=Using the specified source names: '{0}'.
PackageSourceNotFound=No package source with the name '{0}' was found.
UnspecifiedSource=Multiple non-default sources are available, but the default source is not. A source name must be specified.
###PSLOC
Expand Down
10 changes: 7 additions & 3 deletions src/ChocolateyGet.psd1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@{
RootModule = 'ChocolateyGet.psm1'
ModuleVersion = '2.1.0'
ModuleVersion = '3.0.0'
GUID = 'c1735ed7-8b2f-426a-8cbc-b7feb6b8288d'
Author = 'Jianyun'
Copyright = ''
Expand All @@ -10,12 +10,16 @@
PowerShellVersion = if ($PSEdition -eq 'Core') {
'7.0.1'
} else {
'3.0'
'5.1'
}
RequiredModules = @(
@{
ModuleName='PackageManagement';
ModuleName='PackageManagement'
ModuleVersion='1.1.7.2'
},
@{
ModuleName='Foil'
ModuleVersion='0.0.3'
}
)
PrivateData = @{
Expand Down
5 changes: 4 additions & 1 deletion src/ChocolateyGet.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[string]$ScriptPath = Split-Path (Get-Variable MyInvocation -Scope Script).Value.MyCommand.Definition -Parent

# Define provider related variables
$script:PackageSourceName = "Chocolatey"
$script:PackageSource = "Chocolatey"
$script:additionalArguments = "AdditionalArguments"
$script:AllVersions = "AllVersions"
$script:AcceptLicense = "AcceptLicense"
Expand All @@ -17,6 +17,9 @@ if ($PSEdition -eq 'Desktop' -and -not $env:CHOCO_CLI) {
if (-not $env:ChocolateyInstall) {
$env:ChocolateyInstall = "$($env:ProgramData)\chocolatey"
}
} elseif (-not (Get-ChocoPath)) {
Write-Debug ("Choco not already installed")
$ChocoExePath = Install-ChocoBinaries
}

# Utility variables
Expand Down
37 changes: 15 additions & 22 deletions src/private/ConvertTo-SoftwareIdentity.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,34 @@ function ConvertTo-SoftwareIdentity {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline)]
[string[]]
[object[]]
$ChocoOutput,

[Parameter()]
[string]
$RequestedName,
$Name,

[Parameter()]
[string]
$Source = $script:PackageSourceName
$Source = $script:PackageSource
)

begin {
$packageRegex = "^(?<name>[\S]+)[\|\s](?<version>[\S]+)"
$packageReportRegex="^[0-9]*(\s*)(packages installed)"
}

process {
# Each line we get from choco.exe isnt necessarily a package, but it could be
foreach ($packageCandidate in $ChocoOutput) {
if (($packageCandidate -Match $packageRegex) -and ($packageCandidate -notmatch $packageReportRegex) -and $Matches.name -and $Matches.version) {
# If a particular package name wasnt queried for by the user, return everything that choco does
if (-not ($RequestedName) -or (Test-PackageName -RequestedName $RequestedName -PackageName $Matches.name)) {
# Return a new SWID based on the output from choco
Write-Debug "Package identified: $($Matches.name), $($Matches.version)"
$swid = @{
FastPackageReference = $Matches.name+"#"+ $Matches.version.TrimStart('v')+"#"+$Source
Name = $Matches.name
Version = $Matches.version.TrimStart('v')
versionScheme = "MultiPartNumeric"
FromTrustedSource = $true
Source = $Source
}
New-SoftwareIdentity @swid
# If a particular package name wasnt queried for by the user, return everything that choco does
if (-not ($Name) -or (Test-PackageName -RequestedName $Name -Name $packageCandidate.Name)) {
# Return a new SWID based on the output from choco
Write-Debug "Package identified: $($packageCandidate.Name), $($packageCandidate.version)"
$swid = @{
FastPackageReference = $packageCandidate.Name+"#"+ $packageCandidate.version.TrimStart('v')+"#"+$Source
Name = $packageCandidate.Name
Version = $packageCandidate.version.TrimStart('v')
versionScheme = "MultiPartNumeric"
FromTrustedSource = $true
Source = $Source
}
New-SoftwareIdentity @swid
}
}
}
Expand Down
38 changes: 24 additions & 14 deletions src/private/Find-ChocoPackage.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function Find-ChocoPackage {

if ($options -and $options.ContainsKey('Source')) {
# Finding the matched package sources from the registered ones
Write-Verbose ($LocalizedData.SpecifiedSourceName -f ($options['Source']))
Write-Verbose ($LocalizedData.SpecifiedSource -f ($options['Source']))
if ($RegisteredPackageSources.Name -eq $options['Source']) {
# Found the matched registered source
$selectedSource = $options['Source']
Expand All @@ -42,9 +42,9 @@ function Find-ChocoPackage {
if ($RegisteredPackageSources.Count -eq 1) {
# If no source name is specified and only one source is available, use it
$selectedSource = $RegisteredPackageSources[0].Name
} elseif ($RegisteredPackageSources.Name -eq $script:PackageSourceName) {
} elseif ($RegisteredPackageSources.Name -eq $script:PackageSource) {
# If multiple sources are avaiable but none specified, default to using Chocolatey.org - if present
$selectedSource = $script:PackageSourceName
$selectedSource = $script:PackageSource
} else {
# If Chocoately.org is not present and no source specified, throw an exception
ThrowError -ExceptionName 'System.ArgumentException' `
Expand All @@ -57,21 +57,31 @@ function Find-ChocoPackage {
Write-Verbose "Source selected: $selectedSource"

$chocoParams = @{
Search = $true
Package = $name
SourceName = $selectedSource
Name = $Name
Source = $selectedSource
}

if ($requiredVersion) {
$chocoParams.Add('Version',$requiredVersion)
} elseif ($minimumVersion -or $maximumVersion -or $options.ContainsKey($script:AllVersions)) {
# Choco does not support searching by min or max version, so if a user is picky we'll need to pull back all versions and filter ourselves
$chocoParams.Add('AllVersions',$true)
if ($requiredVersion -or $minimumVersion -or $maximumVersion -or $options.ContainsKey($script:AllVersions)) {
if ($requiredVersion) {
$chocoParams.Add('Version',$requiredVersion)
} else {
# Choco does not support searching by min or max version, so if a user is picky we'll need to pull back all versions and filter ourselves
$chocoParams.Add('AllVersions',$true)
}

if (-not $env:CHOCO_NONEXACT_SEARCH) {
# Limit NuGet API result set to just the specific package name if version is specified
# Have to keep choco pinned to 0.10.13 due to https://github.com/chocolatey/choco/issues/1843 - should be fixed in 0.10.16, which is still in beta
$chocoParams.Add('Exact',$true)
}
}

# Return the result without additional evaluation, even if empty, to let PackageManagement handle error management
# Will only terminate if Invoke-Choco fails to call choco.exe
Invoke-Choco @chocoParams |
Where-Object {Test-PackageName -PackageName $_.Name -RequestedName $Name} |
# Will only terminate if Choco fails to call choco.exe
$(if ($script:NativeAPI) {
Invoke-ChocoAPI -Search @chocoParams
} else {
Get-ChocoPackage @chocoParams | ConvertTo-SoftwareIdentity -Name $Name -Source $selectedSource
}) | Where-Object {Test-PackageName -Name $_.Name -RequestedName $Name} |
Where-Object {Test-PackageVersion -Package $_ -RequiredVersion $RequiredVersion -MinimumVersion $MinimumVersion -MaximumVersion $MaximumVersion}
}
6 changes: 5 additions & 1 deletion src/private/Get-PackageSources.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Utility function - Read the registered package sources from its configuration file
function Get-PackageSources {
Invoke-Choco -SourceList
if ($script:NativeAPI) {
Invoke-ChocoAPI -SourceList
} else {
Get-ChocoSource
}
}
Loading

0 comments on commit 7fc241b

Please sign in to comment.