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

winget should not error when installing the exact version of a package that is already installed #4262

Open
jantari opened this issue Mar 12, 2024 · 6 comments
Labels
Issue-Bug It either shouldn't be doing this or needs an investigation.

Comments

@jantari
Copy link

jantari commented Mar 12, 2024

Brief description of your issue

When a package X of version Y is currently installed on the computer, attempting to install that exact package X in version Y again should not result in an error, because there is no operation that failed, it is simply a successful no-op.

The --force parameter exists to force a reinstall if the user desires.

Steps to reproduce

# I am very sorry for the german localized output and error messages, but this is just how winget behaves on my system sadly ....

Administrator in ~
❯ winget list -q GIMP.GIMP --source winget
Name           ID        Version Verfügbar
------------------------------------------
GIMP 2.10.34-2 GIMP.GIMP 2.10.34 2.10.36

Administrator in ~
❯ winget install --id 'GIMP.GIMP' --exact --version '2.10.34' --silent --source winget
Es wurde bereits ein vorhandenes Paket gefunden. Es wird versucht, das installierte Paket zu aktualisieren...
Kein verfügbares Upgrade gefunden.
In den konfigurierten Quellen sind keine neueren Paketversionen verfügbar.

Administrator in ~
❯ $LASTEXITCODE
-1978335189

Administrator in ~
❯

Expected behavior

Winget should exit with return code 0 for success (nothing to do, the desired state is equal to the current state).

Actual behavior

Winget exits with exit code -1978335189 and the message "No applicable update found" when there was no intention to perform an update of any kind.

Environment

# again, terribly sorry for the localized output,
# I know it's not helpful like this but I don't see how I can change wingets' language ...

Windows-Paket-Manager v1.7.10582
Copyright (c) Microsoft Corporation. Alle Rechte vorbehalten.

Windows: Windows.Desktop v10.0.19045.4046
Systemarchitektur: X64
Paket: Microsoft.DesktopAppInstaller v1.22.10582.0

WinGet-Verzeichnisse
-----------------------------------------------------------------------------------------------------------------------------------------
Protokolle                                   %LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\DiagOutputDir
Benutzereinstellungen                        %LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\settings.json
Verzeichnis für portierbare Links (Benutzer) %LOCALAPPDATA%\Microsoft\WinGet\Links
Portables Linkverzeichnis (Computer)         C:\Program Files\WinGet\Links
Portierbarer Paketstamm (Benutzer)           %LOCALAPPDATA%\Microsoft\WinGet\Packages
Portierbarer Paketstamm                      C:\Program Files\WinGet\Packages
Portierbares Paketstamm (x86)                C:\Program Files (x86)\WinGet\Packages
Installationsprogrammdownloads               %USERPROFILE%\Downloads

Links
-----------------------------------------------------------------------------------------
Datenschutzerklärung              https://aka.ms/winget-privacy
Lizenzvereinbarung                https://aka.ms/winget-license
Hinweise von Drittanbietern       https://aka.ms/winget-3rdPartyNotice
Startseite                        https://aka.ms/winget
Windows Store-Nutzungsbedingungen https://www.microsoft.com/en-us/storedocs/terms-of-sale

Administratoreinstellung                  Status
-----------------------------------------------------
LocalManifestFiles                        Deaktiviert
BypassCertificatePinningForMicrosoftStore Deaktiviert
InstallerHashOverride                     Deaktiviert
LocalArchiveMalwareScanOverride           Deaktiviert
@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs-Triage Issue need to be triaged label Mar 12, 2024
Copy link

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Open similar issues:

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

@jantari
Copy link
Author

jantari commented Mar 12, 2024

Additional context for why this behavior change is so important:

Many computer systems, and as such the software installed on them, are managed with the intention of conforming to a certain, defined state and idempotency, i.e. a system or artifact such as a container image cannot simply change because it felt like it or because time has passed. Versions of software dependencies must be tested and updated in a controlled manner and are thus defined explicitly or pinned.

As such, installing a specific version of a package such as a Java JDK would be the norm.

We can currently install the latest version of a package initially, then not update it later. This behavior is often fine for systems that don't have to be 100% reproducible and don't have strict version requirements. This scenario is enabled by wingets --no-upgrade switch. This switch is important and works.

But when we want to install a specific version of a package initially, and then stay on that version until someone explicitly chooses that it may be updated, we run into this error.

We cannot use --no-upgrade because when an explicit version for a package is desired, it is not clear whether that constitutes an upgrade or not before winget install runs (at the time one chooses the parameters to pass). If I explicitly tell winget to install GIMP version 2.10.34, that may very well be an update on, say, 14 out of 60 targeted systems. So setting --no-upgrade is wrong and will not accomplish the goal of ensuring all 60 systems are on that specific version of GIMP. We also cannot use --force, because this causes a reinstall rather than a no-op when the same exact version is already installed. Reinstalling software in-place is often harmless, but causes an outage because the software is briefly unavailable, introduces risk because re-installation of software can always fail due to transient issues such as a reboot happening to be pending at the time or files being in use etc. and it also just wastes time because a no-op could be done in less than a second but uninstalling and reinstalling certain software can take minutes. Forcing an in-place reinstall is certainly something that we wouldn't do by default, just to work around this issue, if it could be solved any other way.

Thanks.

@denelon denelon added Issue-Bug It either shouldn't be doing this or needs an investigation. and removed Needs-Triage Issue need to be triaged labels Mar 12, 2024
@denelon
Copy link
Contributor

denelon commented Mar 12, 2024

@jantari I've had changes of opinion about this scenario over time.

At this point with the new repair command, I think it does make sense for WinGet to essentially no-op when the specified version matches the installed version without "--force".

I think of this internally as a "feature" since we're intentionally changing the current behavior, which was implemented as designed, but as it's being reported as a "bug" I'll keep the bug label. I'd like to see other folks add their 👍to help raise the priority.

@jantari
Copy link
Author

jantari commented Mar 12, 2024

Thanks. If there was a different exit code, I could also handle the scenario in scaffolding scripts.

But currently, when specifying a lower version than installed:

winget install --id 'GIMP.GIMP' --exact --version '2.10.30' --silent --source winget

This returns the same exit code -1978335189, even though the users' intention was to downgrade the software.
I would have to re-run winget with --force to get the desired result, but I can't know that from the exit code.

This is a success scenario / no-op (same version desired as is installed):

winget install --id 'GIMP.GIMP' --exact --version '2.10.34' --silent --source winget

But fails with the same exact error. If I were to re-run this with --force, I'm in trouble. But I can't know that from wingets' behavior or exit code.

It's a damned if I do, damned if I don't situation. Either way I'm going to break things some percent of the time. I would have to perform my own magic-fuzzy-version-number-matching ahead of running winget to determine whether I need to use --force (at which point, If I determine the versions are identical, I just wouldn't run winget install anymore) - but that's something I'd rather not re-implement when winget already exists and handles the highly complex task of version matching.

I hope I'm able to get the usecase and issue across.

@denelon
Copy link
Contributor

denelon commented Mar 12, 2024

Yeah, I also don't know if there is a reasonable Expected Return Code that might help more in this particular case. If that return code is unique to this scenario maybe we could add something to that affect.

"ExpectedReturnCodes": {
  "type": [ "array", "null" ],
  "items": {
    "type": "object",
    "title": "ExpectedReturnCode",
    "properties": {
      "InstallerReturnCode": {
        "$ref": "#/definitions/InstallerReturnCode"
      },
      "ReturnResponse": {
        "type": "string",
        "enum": [
          "packageInUse",
          "packageInUseByApplication",
          "installInProgress",
          "fileInUse",
          "missingDependency",
          "diskFull",
          "insufficientMemory",
          "invalidParameter",
          "noNetwork",
          "contactSupport",
          "rebootRequiredToFinish",
          "rebootRequiredForInstall",
          "rebootInitiated",
          "cancelledByUser",
          "alreadyInstalled",
          "downgrade",
          "blockedByPolicy",
          "systemNotSupported",
          "custom"
        ]
      },
      "ReturnResponseUrl": {
        "$ref": "#/definitions/Url",
        "description": "The return response url to provide additional guidance for expected return codes"
      }
    }
  },

@jantari
Copy link
Author

jantari commented Mar 12, 2024

Yeah, I also don't know if there is a reasonable Expected Return Code that might help more in this particular case. If that return code is unique to this scenario maybe we could add something to that affect.

I don't mean a return code from the installer, I mean the return code winget itself produces in this scenario. This is controllable by you and doesn't need special consideration in the manifests etc.

-1978335189 is documented here:

https://github.com/microsoft/winget-cli/blob/master/doc/windows/package-manager/winget/returnCodes.md#general-errors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Bug It either shouldn't be doing this or needs an investigation.
Projects
None yet
Development

No branches or pull requests

2 participants