Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(scoop-status): sanitize app names and import Get-UserAgent if missing #6252

Open
wants to merge 13 commits into
base: develop
Choose a base branch
from

Conversation

BinToss
Copy link

@BinToss BinToss commented Dec 20, 2024

Description

The first commit improves PowerShell's ability to trace a failed call to Get-UserAgent. It had noted Where-Object or Get-ChildItem calls in scoop-status.ps1 as the cause despite the error being thrown by manifest.ps1's url_manifest function.

Later commits improve error handling across the call chains and the last commit imports the Get-UserAgent function when it isn't already imported.

Motivation and Context

A lack of argument sanitation and an instance of bad error handling caused undefined behavior an error message that didn't make sense. As a result, the root cause was difficult to trace.

Resolves #6251, #6103

How Has This Been Tested?

I iterated changes and ran scoop status after every iteration until the root causes were diagnosed and fixed. Unmodified scripts were not directory tested. As such, they may break if they relied on undefined behavior caused by a lack of argument sanitation.

Checklist:

  • I have read the Contributing Guide.
  • I have ensured that I am targeting the develop branch.
  • I have updated the documentation accordingly.
  • I have updated the tests accordingly.
  • I have added an entry in the CHANGELOG.

@BinToss BinToss changed the title fix(scoop-status): do not loop through empty array; do not pass empty… fix(scoop-status): sanitize app names and import Get-UserAgent if missing Dec 20, 2024
@BinToss
Copy link
Author

BinToss commented Dec 22, 2024

scoop-status.sp1 does not yet have any tests and thorough testing would require a larger refactor. For now, I've added the test suite and one test for its one public function.

@BinToss
Copy link
Author

BinToss commented Dec 22, 2024

Is there a conventional-changelog config I'm unaware of? Updating the changelog with conventional-changelog-cli with the angular or conventionalcommits presets will only include fix, feat, perf, and breaking changes in the changelog.

@BinToss BinToss marked this pull request as ready for review December 22, 2024 06:11
lib/manifest.ps1 Outdated
Comment on lines 17 to 19
if (!(Get-Command Get-UserAgent -ErrorAction SilentlyContinue)) {
Import-Module "$PSScriptRoot/download.ps1" -Function 'Get-UserAgent'
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this if statement imports Get-UserAgent if a *suspected* race condition causes the function to be called before it's imported by a separate script. I don't know why so many of Scoop's scripts call functions without explicitly importing them beforehand. That's a refactor for another day.

Comment on lines 58 to 61
[string[]] $appNames = Get-ChildItem $dir -Directory -Name -Exclude 'scoop' | Where-Object Length -GT 0
if ($appNames.Length -eq 0) { return }

foreach ($app in $appNames) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • fix: refactor Where-Object name -NE 'scoop' to Get-ChildItem's Exclude parameter. If the input object didn't have a Name parameter, an error would occur. This would happen when Get-ChildItem returns a zero-length array such as in the case of an empty or non-existent Global app dir.
  • fix: add Where-Object Length -GT 0 to exclude zero-length strings from $appNames.
  • fix: assign app names array to [string[]] $appNames. Ensures the script halts if any other type is assigned to $appNames and prevents unexpected behavior caused by a type mismatch.
  • style: change ForEach-Object to foreach. A stylistic preference for the $appName in $appNames syntax over $appName = $_.

… strings to `app_status`

- Modify `Get-ChildItem ($dir = appsdir $global)`
  - Add `-Directory` switch; Get only `DirectoryInfo` items.
  - Add `-Name` switch; Return directories' names.
  - Exclude items named 'scoop'.
  - Use Where-Object to filter out zero-length names.
  - Assign to `[string[]] $appNames` to assure type safety.
  - Return if no app names found.
- Change `ForEach-Object` to `foreach`.

These changes improved PowerShell's ability to trace a failed call to Get-UserAgent. It had noted Where-Object or Get-ChildItem calls in scoop-status.ps1 as the cause despite the error being thrown by manifest.ps1's `url_manifest` function.

The stack trace should instead be something like...
at manifest.ps1:18:40 (function url_manifest)
at manifest.ps1:74:24 (function manifest)
at core.ps1:557:17 (function app_status)
at scoop-status.ps1:65:19
…rethrown without changes

Doing so can make debugging difficult.
Only one function is tested and only one of its results is tested.
@BinToss BinToss force-pushed the fix/scoop-status/Get-UserAgent branch from 3ce189a to 6c07782 Compare January 10, 2025 23:44
@BinToss
Copy link
Author

BinToss commented Jan 11, 2025

While refactoring loops, I realized PowerShell can be too forgiving with return vs continue in loops. Specifically, when the loop body is provided as a ScriptBlock. This led to bad practice on my part and I've identified places I should have used continue  used instead of return (which was breaking loops). Oops. I'll push the fix in a few minutes.

This mistake was causing foreach ($app in $appNames) to effectively break instead of continue. This issue was introduced in this pull request; It is not present in the develop branch.

…c readability

`NOT (a OR b OR c OR d)` is slightly easier to understand than `(NOT a) AND (NOT b) AND (NOT c) and (NOT d)`.
This allows manifest.ps1 to import download.ps1 and call `get_proxy` when core.ps1's `get_config` is not in scope.
…iptblocks where `continue` would normally be used in `foreach` loops
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant