choco
choco copied to clipboard
Add option to include install-args in the `choco export` command
It would be nice to have a flag similar to the --include-version-numbers
flag for the choco export
command but for including the installation arguments of a given package (assuming the user has the configuration useRememberedArgumentsForUpgrades
enabled).
Consider the following scenario where I install Git with various installation arguments applied:
cinst -y git.install --installargs "'/COMPONENTS=icons,assoc,assoc_sh,autoupdate,windowsterminal,scalar'" --params "/GitAndUnixToolsOnPath /NoAutoCrlf /WindowsTerminal /NoShellIntegration /NoGuiHereIntegration /NoShellHereIntegration /WindowsTerminalProfile /DefaultBranchName:main /Editor:VisualStudioCode"
then run choco export -o="choco-packages.config"
, however the output XML only contains:
<package id="git.install"/>
whereas it could contain something like so:
<package id="git.install" arguments=" --install-arguments="'/COMPONENTS=icons,assoc,assoc_sh,autoupdate,windowsterminal,scalar'" --package-parameters="'/GitAndUnixToolsOnPath /NoAutoCrlf /WindowsTerminal /NoShellIntegration /NoGuiHereIntegration /NoShellHereIntegration /WindowsTerminalProfile /DefaultBranchName:main /Editor:VisualStudioCode'"" />
This way, when I run cinst -y choco-packages.config
it would apply the initial install-args and params for Git.
Proposed Solution: add --include-install-args
flag to the choco export
command.
I investigated a little further and found that installation arguments are stored under the path:
$env:ChocolateyInstall\.chocolatey\<package>.<version>\.arguments
(again, assuming the user has the config option useRememberedArgumentsForUpgrades
enabled).
Therefore, to implement the proposed enhancement above to the export
command, you could gather package specific installation arguments using some helper functions like these:
Add-Type -AssemblyName System.Security
$entropyBytes = [System.Text.UTF8Encoding]::UTF8.GetBytes("Chocolatey")
Function Unprotect-Arguments {
param([string]$data)
$encryptedByteArray = [System.Convert]::FromBase64String($data)
$decryptedByteArray = [System.Security.Cryptography.ProtectedData]::Unprotect(
$encryptedByteArray,
$entropyBytes,
[System.Security.Cryptography.DataProtectionScope]::LocalMachine
)
return [System.Text.UTF8Encoding]::UTF8.GetString($decryptedByteArray)
}
Function Read-Arguments {
param([string]$packageName)
$directory = Get-ChildItem $env:ChocolateyInstall\.chocolatey -Directory -Filter "$packageName*" | `
Where-Object { $_.Name -match ("$packageName" + "\.[\d\.]+") } | Select-Object -Last 1
If (!($directory)) { return }
$argsFile = Join-Path $directory.fullname ".arguments"
If (Test-Path $argsFile) {
$argsData = Get-Content $argsFile
#Implicitly return result from Unprotect-Arguments
Unprotect-Arguments -data $argsData
}
}
Function Get-LocalPackageInfo {
& choco list -lo -r -y
}
Function Get-PackagesConfigBody($SaveArguments = $false) {
Get-LocalPackageInfo | ForEach-Object {
$packageName = $($_.SubString(0, $_.IndexOf("|")))
$line = ' <package id="' + $packageName + '" '
If ($SaveArguments) {
$line = $line + 'arguments="' + [System.Security.SecurityElement]::Escape($(Read-Arguments $packageName)) + '" '
}
$line = $line + '/>'
$line
}
}
Function Write-PackagesConfig($OutputFile, $SaveArguments = $false) {
$header = "<?xml version=`"1.0`" encoding=`"utf-8`"?>`n<packages>"
$footer = "</packages>"
$body = Get-PackagesConfigBody -SaveArguments $SaveArguments
Write-Output $header $body $footer | Out-File $OutputFile -Encoding ASCII
}
and choco export -o="choco-packages.config" --include-install-args
would utilize something like:
Write-PackagesConfig -OutputFile "choco-packages.config" -SaveArguments $true
Resulting in XML like this:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="gh" arguments=" --cache-location="'C:\Users\jimmy\AppData\Local\Temp\chocolatey'"" />
<package id="git.install" arguments=" --cache-location="'C:\Users\jimmy\AppData\Local\Temp\chocolatey'" --install-arguments="'/COMPONENTS=icons,assoc,assoc_sh,autoupdate,windowsterminal,scalar'" --package-parameters="'/GitAndUnixToolsOnPath /NoAutoCrlf /WindowsTerminal /NoShellIntegration /NoGuiHereIntegration /NoShellHereIntegration /WindowsTerminalProfile /DefaultBranchName:main /Editor:VisualStudioCode'"" />
</packages>
I tested this suite of functions locally and it worked exactly as mentioned above. Only potentially undesired aspect of the result is the --cache-location
being included from the reading of the encrypted .chocolatey/<package>.<version>/.arguments
file.
Here's the script I used (as .txt due to GitHub limitations):
Thanks for adding this issue, I had thought that there already was one posted for this feature request.
This is definitely something that is planned to be added at some point, but it would be in the C# code, not in the PowerShell helper functions. See #1825 for where it would go in.
Also, I discussed this with @gep13, and it is likely that the other install argument would be added with individual elements, instead of via a single arguments
element. This would require that #886 be completed first, and makes changes so the code for parsing CLI arguments can be reused for saved arguments.
Will this add the state of pinned-packages like stated here? https://github.com/chocolatey/choco/pull/1825#issuecomment-491901221
Exactly. So if I pinned VS Code on one machine, it would end up pinned on another machine.
Wasn't quite sure if I should open a new issue, but would find it quite useful to export this with choco export
Wasn't quite sure if I should open a new issue,
@cyber1000 In this case, a new issue would be appropriate. The information about whether a package is pinned or not is stored separately from the saved arguments, and there is not currently a way to pin a package during installation (although I do have a PR open to add that).
👀 Any ETA on this feature getting merged?
We hope to be bringing this in shortly.
Based on the changes in the associated PR's for this issue, I am going to have to bump this issue from the 2.3.0 release, and instead look at this again in the 2.4.0.
The suggested changes to the INuGetService mean that this would essentially be a breaking change, that would need a corresponding change in the Chocolatey Licensed Extension, which we haven't planned to do at the minute.
Instead of holding up the release of 2.3.0, we will look to do the work in this issue in a later release.
Apologies for any inconvenience that this causes.