Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.2 Schema Proposal for Portable and Zip InstallerTypes #1989

Closed
wants to merge 4 commits into from

Conversation

ryfu-msft
Copy link
Contributor

@ryfu-msft ryfu-msft commented Mar 1, 2022

Related to:

This PR adds the necessary schema changes to support installing portable apps and zip files.

Changes:

Settings schema:

  • Addition of WinGetInstallerUserRoot "PortablePackageUserRoot" to allow the user to specify the default root directory where portable apps should be installed to under User scope.
  • Addition of WinGetInstallerMachineRoot "PortablePackageMachineRoot" to allow the user to specify the default root directory where portable apps should be installed to under Machine scope.

InstallerManifest schema:

Changes to 'Installer' object:

  • Addition of NestedInstallers "ArchiveInstallers" which is an object array of NestedInstaller "ArchiveInstaller"
  • Addition of "AppendPathToProcess" which is utilized during the installation of portable apps. We will be registering the app using the App Paths registry subkey. This value would be used to determine whether we should create a ‘Path’ string value in the registry to indicate whether to pre-pend the ‘Path’ value to the PATH environment variable on a per-application, per-process basis

Addition of NestedInstaller "ArchiveInstaller" object:

  • Similar to the existing 'Installer' object but more refined to fit the zip scenario.
  • Addition of "RelativeFilePath" to declare the relative file path to the installer/portable exe that will be installed.
Microsoft Reviewers: Open in CodeFlow

@@ -462,6 +476,17 @@
"InstallerType": {
"$ref": "#/definitions/InstallerType"
},
"NestedInstallers": {
"type": "array",
Copy link
Member

Choose a reason for hiding this comment

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

I don't see how we need more than one installer; what is the scenario?

I can only think of one, and it doesn't need complicated nested installer data. Multiple portables inside an archive, and we want to register app paths for all of them.

Copy link
Contributor

Choose a reason for hiding this comment

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

I could see where someone may put an exe and an MSI into a zip file. If the user has a preference for their installer type, having an array here could be useful. It's a rare edge case, but could be used.

Or where some publishers publish multiple locales in a single zip file, then being able to select the correct locale would be important

Copy link
Member

Choose a reason for hiding this comment

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

We can do all of the multi-installer scenarios by having multiple installers defined at the top level and having all of them reference the same archive, but different files within.

Copy link
Contributor

Choose a reason for hiding this comment

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

We can do all of the multi-installer scenarios by having multiple installers defined at the top level and having all of them reference the same archive, but different files within.

We can, yes, but then there is a lot of duplication of data. The Installer URL and Sha256 at minimum would be repeated for however many installer nodes there are, which could be many when considering the multiplicative effect of locale and architecture.

In my mind it would make updating manifests more difficult and would complicate the flow of wingetcreate and YamlCreate even further. Whereas, having the multi-installer scenarios handled by an array here would likely result in a cleaner user experience

"NestedInstaller": {
"type": "object",
"properties": {
"InstallerLocale": {
Copy link
Member

Choose a reason for hiding this comment

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

If there is only one nested installer per outer installer, then the outer properties are already appropriate. The only data needed for the nested installer would be type and relative path.

Copy link
Contributor

Choose a reason for hiding this comment

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

There could be an x86 binary, an x64 binary, and an arm64 binary all inside a single archive as nested installers. In this case, using the neutral architecture and allowing the nested installers to have the data would make sense.

"nullsoft",
"wix",
"burn",
"portable"
Copy link
Member

@JohnMcPMS JohnMcPMS Mar 1, 2022

Choose a reason for hiding this comment

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

This isn't actually the correct PR for it, but since I'm thinking of it in the context of archives anyway...

I think we need to consider a portableWithInit type (or some other way of achieving it) where the package installer files are intended to stay on the device like portable, but there is also some initialization step to run. Example: I wrote a very simple .pfx viewer that invoked the existing UI on them, but it needed to be run once in order to add the shell verb to the registry. This would be a portable installer as the exe was needed after install, but it was more cumbersome if you would have to run it once by hand since afterward you never needed to use the exe directly again.

Copy link
Member

Choose a reason for hiding this comment

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

It might also require adding uninstall switches that are only applicable to this new type.

@ghost ghost added the Needs-Author-Feedback Issue needs attention from issue or PR author label Mar 1, 2022
@@ -462,6 +476,17 @@
"InstallerType": {
"$ref": "#/definitions/InstallerType"
},
"NestedInstallers": {
"type": "array",
Copy link
Contributor

Choose a reason for hiding this comment

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

I could see where someone may put an exe and an MSI into a zip file. If the user has a preference for their installer type, having an array here could be useful. It's a rare edge case, but could be used.

Or where some publishers publish multiple locales in a single zip file, then being able to select the correct locale would be important

"NestedInstaller": {
"type": "object",
"properties": {
"InstallerLocale": {
Copy link
Contributor

Choose a reason for hiding this comment

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

There could be an x86 binary, an x64 binary, and an arm64 binary all inside a single archive as nested installers. In this case, using the neutral architecture and allowing the nested installers to have the data would make sense.

@ghost ghost removed the Needs-Author-Feedback Issue needs attention from issue or PR author label Mar 1, 2022
},
"InstallerType": {
"$ref": "#/definitions/InstallerType"
},
"ArchiveInstallers": {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we do decide to use multiple ArchiveInstallers, do we have decision on the installer selection behaviors? (i.e. same app with different installers vs different apps)

For example, for some apps, we may have below and we want to install both of them
app1.exe
app2.exe

For some apps, we may have below and we want to only pick 1 to install
app1_x86.exe
app1_x64.exe

I think we can only support 1 of the scenarios above without further manifest entries and making the logic more complex.

Copy link
Contributor Author

@ryfu-msft ryfu-msft Mar 3, 2022

Choose a reason for hiding this comment

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

After discussing this further, we're leaning towards supporting the following scenarios for zip:

1. Single or multiple portable exes contained inside a zip, which will all be installed.

  1. Single or multiple portable exes contained inside a zip, but we will only install one portable.
  2. Single Installer inside a zip.
  3. Multiple installers inside a zip, but only installing one from the selection of installers. This would ensure that we support examples such as zips having multiple architecture installers or multiple locale installers residing in the same zip. If a specific architecture or locale is not specified, winget will choose the best option to install for you.

Regarding the edge case of a zip file containing multiple installerTypes (such as msi and exe), we would need to add support for enabling a user to select which installerType they would prefer to install.

Copy link
Member

Choose a reason for hiding this comment

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

I do not support this:

multiple portable exes contained inside a zip, which will all be installed.

That will just complicate things unnecessarily (although given how messy things are even when we try not to be, it might actually help us to need to handle it head on). But generally, dependencies are a better solution than having a bunch of stuff in a single archive and installing it all. Even if all of those things are in a single archive.

Option 3 is just like our current manifest, but directly supporting the installer set expansion from a single archive rather than requiring repetition of the archive as a top level installer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated the comment above. We decided that we will only install a single portable inside a zip even if the zip archive contains multiple portables. This is to ensure that we limit the complexity that comes with installing multiple packages at the same time. It is better to have that be driven through dependencies when that feature is ready.

Choose a reason for hiding this comment

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

why not just select the main portable exe, chuck a shortcut to the desktop and the folder to program files?

@solomoncyj
Copy link

quick q does the pr cover zips with installers + install data and zips with the application ready to extracted to install location?

@ryfu-msft
Copy link
Contributor Author

quick q does the pr cover zips with installers + install data and zips with the application ready to extracted to install location?

Yes, this PR just covers manifest changes related to zips with installers and zips with portables (where we would extract and copy to a specified install location)

@solomoncyj
Copy link

can the portable zip use a .bat or .ps1 instead on .exe for main executable?

@Trenly
Copy link
Contributor

Trenly commented Mar 7, 2022

can the portable zip use a .bat or .ps1 instead on .exe for main executable?

As far as I know, no. Those are a separate installer type for their own feature

@denelon
Copy link
Contributor

denelon commented Mar 7, 2022

@solomoncyj,

No, we don't support scripts as installers.

"PortableAppMachineRoot": {
"description": "The default root directory where packages are installed to under Machine scope. Applies to the portable installer type.",
"type": "string",
"default": "%LOCALAPPDATA%/WPM_Packages/Machine"
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
"default": "%LOCALAPPDATA%/WPM_Packages/Machine"
"default": "%LOCALAPPDATA%/WinGet_Packages/Machine"

@superusercode
Copy link
Contributor

superusercode commented Apr 2, 2022

Does this current schema cover portable apps within zips that include the runtimes and file structures necessary to run them? i.e. multimc:
image

@denelon
Copy link
Contributor

denelon commented Apr 4, 2022

Does this current schema cover portable apps within zips that include the runtimes and file structures necessary to run them? i.e. multimc: image

I believe this case would be supported as there is only one "portable" application.

@gerardog
Copy link
Contributor

gerardog commented Apr 7, 2022

For zip files containing a group of files belonging to a portable app, and assuming that to add the app to the PATH it must either be shimmed or sym-linked (whatever one the team chooses).

  • Does the schema supports to specify which files need to be added to the path? (yes, more than one)
  • Does it support to symlink/shim a bash script (file with no extension), or .ps1 file? (which are part of the application, not installers).
  • A possible conflict would be if two portable apps may try to create the same shim/symlink. And in that case what happens? first/last one wins?, installation error?

Examples:

  • gsudo ships with a gsudo file (no extension) which is a bash wrapper of gsudo.exe, intended to be called when the app is invoked from WSL (required for improved functionality). In a similar fashion, a PowerShell wrapper also exists. Both wrappers need to be in the Path.
  • Edge case: gsudo generates an alias: sudo => gsudo by creating a sudo.exe symlink to gsudo.exe.

@denelon
Copy link
Contributor

denelon commented Apr 8, 2022

Initially, we're looking at a single portable app inside a .zip file, or a single installer inside a .zip file. The cartesian of other possibilities is a bit much to tackle with the initial implementation. We will continue to iterate to capture more of the other scenarios in future releases.

@solomoncyj
Copy link

For portable apps uninstallation, can winget.just delete install path and component registration?

@ryfu-msft ryfu-msft closed this Jun 22, 2022
@ryfu-msft
Copy link
Contributor Author

Closing this as Portable has been implemented and ZIP schema changes will be addressed and proposed in a separate PR

@ryfu-msft ryfu-msft deleted the schemaProposal branch July 29, 2022 20:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants