microsoft / winget-cli

WinGet is the Windows Package Manager. This project includes a CLI (Command Line Interface), PowerShell modules, and a COM (Component Object Model) API (Application Programming Interface).
https://learn.microsoft.com/windows/package-manager/
MIT License
23.27k stars 1.45k forks source link

Support for "or" dependencies. #1789

Open jedieaston opened 2 years ago

jedieaston commented 2 years ago

Description of the new feature / enhancement

I would like to be able to express that multiple different packages could be used to fufill a dependency. If an application relies on the OpenJDK, it is unlikely that it would rely on a specific vendor's implementation, and we shouldn't install a different version if the user already has one. Similarly, ReSharper (and other developer tools) rely on any version of Visual Studio being installed, but under the current system we could only express a single version and edition combination.

Proposed technical implementation details

One implementation could be that the dependencies key in the manifest could accept arrays of package id/version combinations in addition to single dependencies, where any value in the array would satisfy the dependency. For example:

# ...
Dependencies:
  PackageDependencies:
  - PackageIdentifier: Microsoft.VC++2013Redist-x64
    MinimumVersion: 12.0.30501.0
  - PackageIdentifier: Microsoft.VC++2013Redist-x86
    MinimumVersion: 12.0.30501.0
  - 
    - PackageIdentifier: Microsoft.VisualStudio.2019.Community
    - PackageIdentifier: Microsoft.VisualStudio.2019.Professional
    - PackageIdentifier: Microsoft.VisualStudio.2019.Enterprise
    - PackageIdentifier: Microsoft.VisualStudio.2022.Community
    - PackageIdentifier: Microsoft.VisualStudio.2022.Professional
    - PackageIdentifier: Microsoft.VisualStudio.2022.Enterprise

The YAML "array of arrays" syntax isn't awesome, so maybe this isn't the best method.

florelis commented 2 years ago

In the Linux world (at least in Gentoo) I've seen "virtual packages" that don't actually install anything but rather have something similar to this kind of "or" dependencies and are considered installed if any of the referenced packages is installed. For example, a virtual "editor" package that is considered installed if vim, emacs or any other editor is installed. Maybe we could do something similar to that. In your example, we could have a virtual VisualStudio package that is seen as installed if any version of Visual Studio is installed, and then have ReSharper and any other tool depend on that single package. The part of checking for any of multiple installed packages could probably use some of the work for multiple ARP entries.

denelon commented 2 years ago

We've also looked at the "provides" / "consumes" model implemented in some package managers. I think it gets a bit messy though. Virtual Packages also could be problematic. with the PackageDependencies, we could have a - OneOfTheFollowing key that contains an array. Without knowing full compatibility for a Virtual Package, the array could at least help ensure the dependent package works for those cases where one of the providers isn't compatible.

I tend to think of Java Runtime Environments as one of the best examples for this scenario.

Trenly commented 2 years ago

Just going through all the feature requests and re-reading them; I think one way to ease the complexity here could be to take advantage of the package identifier split character, where Microsoft.VisualStudio.2022 would match any package that has an identifier beginning with Microsoft.VisualStudio.2022.

This doesn't solve the need / desire for One Of dependencies, but it could make it easier for manifest authors to include swaths of packages which all satisfy the dependency

jedieaston commented 2 years ago

Wildcard dependencies would be interesting, but I'm afraid that if someone added something that fit the wildcard but didn't fit the dependency we could introduce regressions, like if Eclipse.Adoptium.11.* was only JDKs right now, but they eventually started shipping JREs under Eclipse.Adoptium.11.JRE, which wouldn't have the same components. I think we'd either have to define a virtual package (which would be just a list of packages that satisfied a dependency, like Python.Python.3 being any version of Python 3), or have manifests independently list which identifiers would satisfy a dependency.

denelon commented 2 years ago

I think the "or" case is probably still better due to the nature of the nested structure of packages.

What if Visual Studio reorganizes themselves like:

Microsoft.VisualStudio.Community.2019 Microsoft.VisualStudio.Enterprise.2019 Microsoft.VisualStudio.Community.2022 Microsoft.VisualStudio.Enterprise.2022

Taking the Dependency on "Microsoft.VisualStudio" might not work if 2022 was needed.

Virtual packages might work for something like Python where we could say:

Python.Python - take the latest version of all child packages. Python.Python.3 - take the latest 3.y.z version of all child packages. Python.Python.3.9 - take the latest 3.9.z version of all child packages.

It would depend on the logical structure. Since we don't have good logic for channels yet when things can be installed side by side, or the user and machine versions can both be installed, I'd be cautious.