Skip to content

Add an optional installer-host column to package lists - #5320

Merged
Gabriel Dufresne (GabrielDuf) merged 3 commits into
mainfrom
feature/5268-installer-host-column
Aug 25, 2026
Merged

Add an optional installer-host column to package lists#5320
Gabriel Dufresne (GabrielDuf) merged 3 commits into
mainfrom
feature/5268-installer-host-column

Conversation

@GabrielDuf

Copy link
Copy Markdown
Contributor

This pull request introduces a new feature that displays the installer host (i.e., the domain from which a package installer will be downloaded) in package lists. The implementation includes UI, settings, caching, and backend logic to efficiently resolve, display, and optionally hide this information. Additionally, utility and test code has been added to robustly extract and format installer host details.

Installer Host Column Feature:

  • Added a new optional "Installer host" column to package lists, including UI bindings, header text, and visibility logic controlled by a new user setting.
  • Introduced a new settings option "Show the installer host on package lists" in the interface settings, including localization and settings infrastructure.

Backend and Caching Logic:

  • Implemented logic in PackageWrapper to resolve, cache, and expose the installer host and its tooltip, including concurrency controls and a cache eviction strategy.
  • Added backend support for resolving installer URLs and hosts, including WinGet-specific logic and fallback mechanisms.

Utility and Test Code:

  • Added InstallerHostDisplay utility for extracting and formatting hostnames from installer URLs, with robust handling of edge cases.
  • Introduced comprehensive unit tests for installer host extraction and formatting logic.

UI Infrastructure:

  • Added an attached property PackageInstallerHostLoader.Track to trigger installer host loading when a package row is rendered, ensuring on-demand and efficient data loading.

These changes collectively provide users with greater transparency about where package installers are sourced from, while maintaining performance and configurability.

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.

Pull request overview

Adds an optional installer-host column to package lists, backed by lazy URL resolution and caching.

Changes:

  • Adds configurable installer-host UI and settings integration.
  • Resolves and caches installer URLs and hosts.
  • Adds host-formatting utilities and unit tests.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs Exposes WinGet installer URL resolution.
src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/PingetPackageDetailsProvider.cs Retrieves installer URLs from Pinget manifests.
src/UniGetUI.Core.Tools/InstallerHostDisplay.cs Formats installer hosts and URL tooltips.
src/UniGetUI.Core.Tools.Tests/InstallerHostDisplayTests.cs Tests URL and host formatting.
src/UniGetUI.Core.Settings/SettingsEngine_Names.cs Registers the column setting.
src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml Adds the package-list column.
src/UniGetUI.Avalonia/Views/Pages/SettingsPages/Interface_P.axaml Adds the interface setting control.
src/UniGetUI.Avalonia/Views/Controls/PackageInstallerHostLoader.cs Starts loading for realized rows.
src/UniGetUI.Avalonia/ViewModels/SoftwarePages/PackagesPageViewModel.cs Controls header text and visibility.
src/UniGetUI.Avalonia/Models/PackageCollections.cs Implements resolution, caching, and display state.
src/UniGetUI.Avalonia/Infrastructure/SettingsSearchIndex.cs Makes the setting searchable.
src/Languages/lang_en.json Adds English localization strings.

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

Comment thread src/UniGetUI.Avalonia/Models/PackageCollections.cs
Comment thread src/UniGetUI.Avalonia/Models/PackageCollections.cs Outdated

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.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

src/UniGetUI.Avalonia/Models/PackageCollections.cs:392

  • Clearing the entire cache when adding entry 1,025 discards 1,024 valid network-derived results at once. On large result sets or subsequent page/list rebuilds, those packages must query their repositories again, creating periodic request bursts; the icon cache above avoids this with bounded LRU eviction (PackageCollections.cs:39-44, 130-134). Evict only the least-recently-used/oldest entry instead of flushing the cache.
            if (_installerHostCache.Count >= MaxInstallerHostCacheEntries
                && !_installerHostCache.ContainsKey(hash))
            {
                _installerHostCache.Clear();
            }

src/UniGetUI.Avalonia/Models/PackageCollections.cs:330

  • On an Updates row, InstallerHostVersion selects NewVersionString, but this non-WinGet path loads Package.Details, whose helpers resolve against Package.VersionString (the installed version). For example, Cargo selects manifest.versions by details.Package.VersionString (CargoPkgDetailsHelper.cs:47-49), and NuGet builds its manifest URL with that same property (NuGetManifestLoader.cs:16-20). The column can therefore report the old installer’s host rather than the host from which the update will be downloaded. This path needs a version-aware details/URL resolver using InstallerHostVersion.
        if (!Package.Details.IsPopulated)
            await Package.Details.Load().ConfigureAwait(false);

        return Package.Details.InstallerUrl is { } url ? [url.ToString()] : null;

Comment thread src/UniGetUI.Avalonia/Models/PackageCollections.cs

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.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated no new comments.

Suppressed comments (3)

Previously missed (2) — in code that hasn't changed since the last review.

src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/PingetPackageDetailsProvider.cs:551

  • OrdinalIgnoreCase applies to the entire URL, but only the scheme and host are case-insensitive; path and query components can be case-sensitive. As a result, two distinct installer artifacts or signed URLs that differ only by path/query casing are dropped from the returned list (and the new test currently codifies that loss). Please deduplicate with URI-component-aware equality and update the expectation accordingly.
                if (urls.Contains(installer.Url, StringComparer.OrdinalIgnoreCase))
                    continue;
                urls.Add(installer.Url);

src/UniGetUI.Core.Tools/InstallerHostDisplay.cs:36

  • This also compares the complete URL case-insensitively, so JoinUrls hides valid distinct URLs whose path or query differs only by case. Use URI-aware comparison that folds scheme/host but preserves path/query case; the added JoinUrlsListsDistinctUrlsOnSeparateLines test should be adjusted as well.
            string trimmed = (url ?? "").Trim();
            if (trimmed.Length == 0 || distinct.Contains(trimmed, StringComparer.OrdinalIgnoreCase))
                continue;
            distinct.Add(trimmed);

src/UniGetUI.Avalonia/Models/PackageCollections.cs:294

  • Marking the lookup unresolved does not arrange another call after InstallerHostRetryInterval. Resetting _installerHostLoadStarted only helps if virtualization later reattaches or changes this row's data context; a row that stays visible remains at “—” indefinitely after a transient failure. Schedule a lifetime-token-aware retry (and distinguish transient lookup failures from a successful no-URL result to avoid repeatedly querying packages that genuinely have no installer URL).
                    if (resolved.Host.Length > 0)
                        CacheInstallerHost(hash, resolved.Host, resolved.Urls);
                    else
                        MarkInstallerHostUnresolved(hash);

@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": "d99c25e0-a090-11f1-9c19-b9898df72113",
	"headSha": "4539d482ed61e014f439e267a7aa9d18e04e188d",
	"reviewer": "copilot-pull-request-reviewer[bot]"
}

@GabrielDuf
Gabriel Dufresne (GabrielDuf) merged commit fd81227 into main Aug 25, 2026
7 checks passed
@GabrielDuf
Gabriel Dufresne (GabrielDuf) deleted the feature/5268-installer-host-column branch August 25, 2026 14:38
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.

[IMPROVEMENT] Option to show installer host in detailed list of discovery & updates

2 participants