Skip to content

Better support for Side by Side packages #2129

Description

@JohnMcPMS

Description of the new feature / enhancement

winget should better support multiple versions of the same package being installed on the same machine. This happens, and we currently try to pretend it doesn't.

Proposed technical implementation details

The current design is a simple 1:1 mapping between installed artifacts and available packages. This has been largely effective, but it certainly belies the true complexities of some packages / installed states. Any complete solution will have to expand to support a full graph, but fortunately we can do small steps to get there.

As far as available packages go, we can control the graph quite a bit. We currently have only two concepts: package and version. The only available relationship is that packages have 1 to N versions. Dependencies are relevant here, as they are simply references, not containment. The only other concept that I am aware of having been discussed is that of a "group" package (name made up on the spot). This "group" package would name several other packages, which would all be considered a part of the group. Consider a group graph like: python contains {python.3, python.2 } and python.3 contains { python.3.12, python.3.11, ... }. A dependency on python would allow any version to satisfy it, while a dependency on python.3 would require major version 3. Some ordering mechanism or "default" tagging would allow the preferred package to install when appropriate (or to provide the available options for choice when the group is less coupled like JDK/JRE). I mention all of this because the side-by-side support would be strictly required to implement "group" packages. Effectively though, these are still packages in our graph, they just have more complex handling requirements.

The installed artifacts are quite a bit more complex and not under our control. But I believe that they fall into two top level categories: primary components and subcomponents. In reality, there are likely many different flavors of subcomponents that might require special handling, but they are all not primary. Currently the goal of the 1:1 mapping is to create a link between the primary component and the available package. Side-by-side support requires allowing multiple primary components to be associated with available package, but it is not concerned with subcomponents. The issue with current reality is that there are manifests with subcomponent details listed that would likely lead to improper side-by-side views even with only one package version installed (without at least some effort placed there).

So, to cover my entire vision on the graph of relationships:

  1. A "group" package is composed of [1, N] packages (some of which may also be groups)
  2. A package is composed of [1, N] versions
  3. A version is composed of [1, N] installers, which I sneak in here because it is important at an implementation level to have this information so that we can better categorize installed artifacts
  4. An installed package version is composed of [1, N] components, with exactly 1 primary component
  5. A package may be associated with [0, N] installed package versions

For a minimal side-by-side implementation to work, we will need to implement 5, enough of 4 to separate out primary components, and the portions of 3 to allow the improved categorization of the installed package versions.

The achievable graph is much more likely:

graph TD;
    p(Package)-->v1(Available Version 1)
    p-->v2(Available Version 2)
    p-->i1u(Installed Version 1 User)
    p-->i1m(Installed Version 1 Machine)
    p-->i2(Installed Version 3)
    i1u-->pC1u(Primary Component)
    i1m-->pC1m(Primary Component)
    i2-->pC2(Primary Component)
    p-->sub(Subcomponents)
    i1u-->v1
    i1m-->v1
Loading

Note that installed versions are not linked through available versions, but do allow for a potential link back to the available version if it exists. Also note that I am pessimistic about the likelihood of successfully associating subcomponents with their installed version. We could allow for that by having both versioned and unversioned buckets, but I would not start there. Finally, note that side-by-side needs to support not only multiple versions, but potentially the different flavors of a single version (whether differentiated by scope, architecture, etc.)

"Group" packages fit into this model, but we would likely want to have a richer object interface to support them specifically.

Care will need to be taken in designing the user experience to prevent the need for more data than we can comfortably add to the index. We want to be able to lump installed artifacts in with available packages quickly, but at the same time we will need more information than we currently have to be able to determine primary components and the set of versions/flavors of installed items. For programmatic access we can lazily determine some of it with the manifest, but we want to make sure that the CLI experience doesn't force that on winget list, but rather only when a single result is found.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-MatchingIssue related to correlation between installed package and manifestExperimentalThis experimental feature can be enabled in settingsIssue-FeatureThis is a feature request for the Windows Package Manager client.Side-by-SideIssue related to side by side package installation
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions