Skip to content

Honor the configured WinGet scope and architecture in package details - #5521

Merged
Gabriel Dufresne (GabrielDuf) merged 4 commits into
mainfrom
fix/winget-details-installer-scope
Oct 15, 2026
Merged

Gabriel Dufresne (GabrielDuf) merged 4 commits into
mainfrom
fix/winget-details-installer-scope

Conversation

@GabrielDuf

@GabrielDuf Gabriel Dufresne (GabrielDuf) commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Package details and "Download installer" now pick the same WinGet installer that install and update use, honoring the configured scope and architecture.

The bug

With WinGet set to Machine | Global scope, updating Visual Studio Code correctly ran VSCodeSetup-x64. But the details "Installer URL" and every "Download installer" entry point (details page, right-click, toolbar) returned VSCodeUserSetup-x64.

  • Cause: install and update pass --scope and --architecture from the applicable install options. Package details queried Pinget with neither, so Pinget took the first installer for the system architecture. VS Code's manifest lists the user installer before the machine one.
  • Why every download path was affected: the details field and all download paths read Details.InstallerUrl.

Changes

  • One rule for scope and architecture: a package override wins, then the install options. Both are dropped after an "update not applicable" retry. The rule is now WinGetPkgOperationHelper.GetEffectiveScope / GetEffectiveArchitecture, shared by the operation command line and package details, so they can't drift again.

  • In-process details (COM / Pinget helpers): query Pinget with both values. The query runs again without them only when they actually excluded an installer, mirroring the native GetApplicableInstaller fallback.

  • Bundled Pinget CLI details (system winget CLI mode): this used to take Installers[0] outright, because the Rust show --output json returns the raw manifest without a selected installer. It now follows Pinget's selection rules:

    • an installer without a Scope matches any scope
    • architecture is filtered and ranked by system preference
    • a preference that matches nothing falls back to the unconstrained pick

    Users with nothing configured now get the installer that matches their machine instead of the first one listed.

Verification

  • New unit tests cover the scoped query, the retry and no-retry cases, the CLI selection by scope and architecture, installers without a scope, and the fallback.
  • Ran the real in-process provider against the live winget index for Microsoft.VisualStudioCode (temporary test, not committed):
    • no scope → VSCodeUserSetup (reproduces the bug)
    • machine → VSCodeSetup
    • machine + x64 → VSCodeSetup-x64
    • user + x86 → no x86 installer, so it falls back to the unconstrained pick
  • Full UniGetUI.PackageEngine.Tests suite passes. dotnet format whitespace and dotnet format style are clean.

Not checked in the running app on an x64 machine. The test box is ARM64, where the live run returned arm64 URLs.

Closes #5519

Install and update pass --scope and --architecture from the applicable
install options, but package details queried Pinget with neither. Pinget
then picked the first installer applicable to the system architecture,
and many manifests list the user installer before the machine one
(Microsoft.VisualStudioCode: VSCodeUserSetup before VSCodeSetup). The
details "Installer URL" field and every "Download installer" entry point
read Details.InstallerUrl, so a user configured for Machine scope saw and
downloaded the per-user installer while updates correctly used the
machine one.

The effective scope/architecture rule (package override, then options,
dropped after an "update not applicable" retry) is hoisted into
WinGetPkgOperationHelper so the operation command line and package
details cannot drift again. Details now query Pinget with both values,
and retry without them only when they actually excluded an installer,
mirroring the native GetApplicableInstaller fallback.

The bundled Pinget CLI provider (system winget CLI mode) used to take
Installers[0] outright, since the Rust show --output json emits the raw
manifest without a selected installer. It now mirrors Pinget's
selection: an installer without a Scope matches any scope, architecture
is filtered and ranked by system preference, and an unsatisfiable
preference falls back to the unconstrained pick.

Fixes #5519

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Remaining selection gaps can choose installers that differ from updates or cannot run on the current Windows version.

3 open findings
What changed in this PR

Aligns WinGet package details and installer downloads with configured scope and architecture, addressing #5519.

Changes:

  • Shares scope and architecture resolution with operation commands.
  • Adds preference-aware installer selection and fallback for both Pinget providers.
  • Adds tests for preferences, missing scope, and fallback behavior.
File Description
src/​UniGetUI.PackageEngine.Tests/​WinGetManagerTests.cs Tests installer selection and fallback.
src/​UniGetUI.PackageEngine.Managers.WinGet/​Helpers/​WinGetPkgOperationHelper.cs Extracts shared preference resolution.
src/​UniGetUI.PackageEngine.Managers.WinGet/​ClientHelpers/​PingetPackageDetailsProvider.cs Applies preferences to queries and CLI manifest selection.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Brokered update architecture and cached details can still disagree with the installer selected from current preferences.

1 open finding
3 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Medium severity Package details retain stale installer URL after scope changes

src/​UniGetUI.PackageEngine.Managers.WinGet/​ClientHelpers/​PingetPackageDetailsProvider.cs:541

Installer selection now depends on mutable install options, but the details view reuses populated metadata. PackageDetailsViewModel.LoadDetailsAsync skips loading when IsPopulated is true (lines 244–246), and PackageDetailsWindow.SaveInstallOptionsAsync only saves the options (lines 160–165). Open details with user scope, save a machine-scope package override, then reopen the same package: the displayed URL remains the user installer. Installation uses the new preference, and downloads reload details, so they can disagree with the displayed URL. Refresh or invalidate installer metadata when the effective scope or architecture changes, and add a regression test for this sequence.

🧠 Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Option changes can still leave downloads or open details views using stale installer metadata.

2 open findings
1 resolved since last review

🧠 Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No blocking defects remain; the documentation correction is non-blocking.

0 open findings

2 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Low severity Correct XML summaries for elevation and architecture overrides

src/​UniGetUI.PackageEngine.Managers.WinGet/​Helpers/​WinGetPkgOperationHelper.cs:240

The existing XML summary now describes ApplyOperationOverrides as checking elevation, but this hook only overrides the architecture for updates. Move the elevation summary back to ApplyElevationRequirements and document the architecture override here so callers see the correct behavior.

🧠 Review effort: Balanced

@randy-but-a-ro randy-but-a-ro Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 Pull request was approved automatically: the AI review is complete and all its review threads are resolved. 🎉

Integration Details
{
	"deliveryId": "5bb45650-c8bf-11f1-82a0-f8eb7c783432",
	"headSha": "10530d7863b89640783b877c70b781ee2d4a4c6d",
	"reviewer": "copilot-pull-request-reviewer[bot]"
}

@GabrielDuf
Gabriel Dufresne (GabrielDuf) merged commit 288ef55 into main Oct 15, 2026
12 of 14 checks passed
@GabrielDuf
Gabriel Dufresne (GabrielDuf) deleted the fix/winget-details-installer-scope branch October 15, 2026 18:11
martesi pushed a commit to martesi/UniGetUI that referenced this pull request Oct 25, 2026
Restore shared loading coordination and complete npm, operation-test, launcher, and platform integration. Keep Cargo metadata acquisition cancellable when FileStream encounters a sharing lock before the native lock call, and close HTTP fixtures without a shutdown race.

Upstream-Commit: 6ef60b4
Upstream-PR: Devolutions#5070

Upstream-Commit: c87bd6b
Upstream-PR: Devolutions#5039

Upstream-Commit: 566ea0c
Upstream-PR: Devolutions#5346

Upstream-Commit: 4f8a820
Upstream-PR: Devolutions#5348

Upstream-Commit: 8220a4b
Upstream-PR: Devolutions#5402

Upstream-Commit: 288ef55
Upstream-PR: Devolutions#5521

Upstream-Commit: 83efec6
Upstream-PR: Devolutions#5569
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] UniGet UI 2026.3.1 ignores the configured scope and downloads the wrong package.

2 participants