Skip to content

Allow versioning in downloaded installer file names - #5319

Merged
Gabriel Dufresne (GabrielDuf) merged 6 commits into
mainfrom
installer-download-file-names
Aug 24, 2026
Merged

Allow versioning in downloaded installer file names#5319
Gabriel Dufresne (GabrielDuf) merged 6 commits into
mainfrom
installer-download-file-names

Conversation

@GabrielDuf

Copy link
Copy Markdown
Contributor

This pull request introduces a user-configurable setting for naming downloaded installer files, allowing users to choose between several naming schemes (e.g., including version or package ID in the file name). It also implements the logic for building installer file names according to the selected scheme, updates the UI and settings infrastructure to support this option, and adds comprehensive tests for the new functionality. Additionally, it introduces a new property to package managers to indicate if the installer URL follows the package version.

Installer file naming customization:

  • Added InstallerFileNaming utility with logic to build installer file names according to a user-selected scheme (publisher name, package name and version, package ID and version, or publisher name and version), including extension handling and sanitization.
  • Added new setting InstallerFileNameScheme to the settings engine, exposed in the UI as a combobox in the Operations settings page, and indexed for search.

Installer download flow improvements:

  • Updated the download installer action to use the new naming logic and ask the user for the save location with the generated file name.

Testing and reliability:

  • Added a comprehensive test suite for InstallerFileNaming, covering all naming schemes, extension extraction, version normalization, and edge cases.

Package manager interface update:

  • Added InstallerUrlFollowsPackageVersion property to IPackageManager and implemented it in relevant package managers, allowing for future logic that depends on whether the installer URL changes with the package version.

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 configurable installer filename schemes and integrates them into download workflows.

Changes:

  • Adds filename generation, sanitization, extension handling, and tests.
  • Adds settings UI and search indexing.
  • Adds manager metadata for version-dependent installer URLs.

Reviewed changes

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

Show a summary per file
File Description
Package.cs Generates installer filenames with resolved versions.
PackageManager.cs Adds default URL-version behavior.
NullPackageManager.cs Implements the new interface property.
BaseNuGet.cs Marks NuGet URLs as version-specific.
Cargo.cs Marks Cargo URLs as version-specific.
IPackageManager.cs Exposes URL-version behavior.
InstallerFileNaming.cs Implements filename schemes and sanitization.
InstallerFileNamingTests.cs Tests naming behavior and edge cases.
SettingsEngine_Names.cs Registers the filename setting.
Operations.axaml.cs Populates naming options.
Operations.axaml Adds the settings UI.
PackageDetailsWindow.axaml.cs Uses the application download workflow.
SettingsSearchIndex.cs Indexes the new setting.
AvaloniaPackageOperationHelper.cs Improves extension extraction for save dialogs.
Suppressed comments (1)

src/UniGetUI.Core.Tools/InstallerFileNaming.cs:110

  • A raw substring check can suppress the requested version even when only a different token contains it—for example, version 2.0 is considered present in tool-12.0, and single-digit versions match almost any stem. Check for the version as a delimiter-bounded filename token instead, while retaining the intended jre-8u451-... case.
        if (stem.Contains(version, StringComparison.OrdinalIgnoreCase))
            return stem;

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/UniGetUI.Core.Tools/InstallerFileNaming.cs Outdated
Comment thread src/UniGetUI.Avalonia/Views/Pages/SettingsPages/Operations.axaml.cs
Comment thread src/UniGetUI.Avalonia/Views/Pages/SettingsPages/Operations.axaml

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 2 comments.

Suppressed comments (1)

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

src/UniGetUI.Core.Tools.Tests/InstallerFileNamingTests.cs:11

  • These tests write directly to CoreData.UniGetUIUserConfigurationDirectory, and teardown deletes the user's existing installer-name preference instead of restoring it. Running the suite locally can therefore modify real application settings. Isolate the test with TEST_DataDirectoryOverride, as the other settings-backed Core.Tools tests do.
    public void Dispose()
    {
        Settings.SetValue(Settings.K.InstallerFileNameScheme, "");
        GC.SuppressFinalize(this);

Comment thread src/UniGetUI.Avalonia/Views/DialogPages/PackageDetailsWindow.axaml.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 20 out of 20 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.Core.Tools/InstallerFileNaming.cs:40

  • Cargo details use installer type Source and a /crates/{id}/{version}/download URL with no extension, but this map has no source fallback. Every versioned scheme therefore produces an extensionless Cargo artifact, and the single-file picker subsequently falls back to an .exe filter even though the payload is a .crate archive. Add the Cargo fallback extension (or expose and map a Cargo-specific installer type).
        ["nupkg"] = ".nupkg",

src/UniGetUI.Core.Tools.Tests/InstallerFileNamingTests.cs:162

  • This test is platform-dependent because Sanitize delegates to Path.GetInvalidFileNameChars(): : is invalid on Windows but valid on Linux and macOS, so the supported cross-platform test project produces Foo: Bar Baz_1.0.exe there. Use only a universally invalid character such as / in this assertion.
                "Foo: Bar / Baz",

Comment thread src/UniGetUI.Avalonia/Views/DialogPages/PackageDetailsWindow.axaml.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 23 out of 23 changed files in this pull request and generated 1 comment.

Comment thread src/UniGetUI.Core.Tools.Tests/InstallerFileNamingTests.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 23 out of 23 changed files in this pull request and generated no new comments.

Suppressed comments (2)

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

src/UniGetUI.Avalonia/ViewModels/DialogPages/OperationViewModel.cs:302

  • This role-based fallback still loses the originating referral for install operations. A bundle install (PackageBundlesPage.cs:277) and a reinstall launched from Installed Packages (InstalledPackagesPage.cs:381) are both plain InstallPackageOperations, so opening their details from the operation list reports subsequent installs/downloads as DIRECT_SEARCH instead of FROM_BUNDLE or ALREADY_INSTALLED. Preserve the referral on the operation and pass it through here rather than inferring it from Role.
        var referral = packageOp.Role is OperationType.Update or OperationType.Uninstall
            ? TEL_InstallReferral.ALREADY_INSTALLED
            : TEL_InstallReferral.DIRECT_SEARCH;

src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Package.cs:350

  • For managers whose installer URL always resolves to the latest release, this fallback can label the payload with an unrelated installed version. For example, Pip loads its URL from the unversioned /pypi/{id}/json endpoint, so an installed 1.0 package with no equivalent currently loaded can download 2.0 as ..._1.0.whl; the new ListedVersionIsUsedWhenNoEquivalentIsLoaded test codifies this mismatch. When the latest version cannot be resolved, omit it or obtain it from manager metadata rather than falling back to VersionString.
            return VersionString;

@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": "39371e70-9ffa-11f1-9b6e-381295aeb7a4",
	"headSha": "65b21fd9cba416fd8f18adef0be4e200115bccc5",
	"reviewer": "copilot-pull-request-reviewer[bot]"
}

@GabrielDuf
Gabriel Dufresne (GabrielDuf) merged commit d23150c into main Aug 24, 2026
10 of 11 checks passed
@GabrielDuf
Gabriel Dufresne (GabrielDuf) deleted the installer-download-file-names branch August 24, 2026 20:46
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.

Download Installer - Need Improvement for Naming Installer Example "PackageName_Version"

2 participants