From 9aa3807dfc0d2e2c1432ee290152b38c0f9a2d60 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Wed, 7 Dec 2022 13:17:20 -0600 Subject: [PATCH 1/2] Add Experimental Argument for UninstallPrevious in Upgrade Flow --- doc/Settings.md | 11 +++++++++++ schemas/JSON/settings/settings.schema.0.2.json | 5 +++++ src/AppInstallerCLICore/Argument.cpp | 2 ++ src/AppInstallerCLICore/Commands/InstallCommand.cpp | 1 + src/AppInstallerCLICore/Commands/UpgradeCommand.cpp | 1 + src/AppInstallerCLICore/ExecutionArgs.h | 1 + src/AppInstallerCLICore/Resources.h | 1 + src/AppInstallerCLICore/Workflows/InstallFlow.cpp | 5 +++-- src/AppInstallerCLIE2ETests/BaseCommand.cs | 1 + src/AppInstallerCLIE2ETests/FeaturesCommand.cs | 1 + src/AppInstallerCLIE2ETests/SetUpFixture.cs | 1 + .../Shared/Strings/en-us/winget.resw | 3 +++ src/AppInstallerCommonCore/ExperimentalFeature.cpp | 4 ++++ .../Public/winget/ExperimentalFeature.h | 1 + .../Public/winget/UserSettings.h | 2 ++ src/AppInstallerCommonCore/UserSettings.cpp | 1 + 16 files changed, 39 insertions(+), 2 deletions(-) diff --git a/doc/Settings.md b/doc/Settings.md index f0d09d3b2d..3bbbabf775 100644 --- a/doc/Settings.md +++ b/doc/Settings.md @@ -254,6 +254,17 @@ You can enable the feature as shown below. }, ``` +### uninstallPreviousArgument + +This feature enables the Windows Package Manager to override the upgrade behavior to UninstallPrevious by passing the `--uninstall-previous` argument with any command. +You can enable the feature as shown below. + +```json + "experimentalFeatures": { + "uninstallPreviousArgument": true + }, +``` + ### dependencies Experimental feature with the aim of managing dependencies, as of now it only shows package dependency information. You can enable the feature as shown below. diff --git a/schemas/JSON/settings/settings.schema.0.2.json b/schemas/JSON/settings/settings.schema.0.2.json index 5bec3b7b82..6b0dd0b899 100644 --- a/schemas/JSON/settings/settings.schema.0.2.json +++ b/schemas/JSON/settings/settings.schema.0.2.json @@ -213,6 +213,11 @@ "description": "Enable argument to open default logs location", "type": "boolean", "default": false + }, + "uninstallPreviousArgument": { + "description": "Enable argument to override upgrade behavior to UninstallPrevious", + "type": "boolean", + "default": false } } } diff --git a/src/AppInstallerCLICore/Argument.cpp b/src/AppInstallerCLICore/Argument.cpp index 429fd27891..f74d3a3ace 100644 --- a/src/AppInstallerCLICore/Argument.cpp +++ b/src/AppInstallerCLICore/Argument.cpp @@ -105,6 +105,8 @@ namespace AppInstaller::CLI return Argument{ "product-code"_liv, NoAlias, Args::Type::ProductCode, Resource::String::ProductCodeArgumentDescription, ArgumentType::Standard, false }; case Args::Type::OpenLogs: return Argument{ "open-logs"_liv, NoAlias, "logs"_liv, Args::Type::OpenLogs, Resource::String::OpenLogsArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::OpenLogsArgument}; + case Args::Type::UninstallPrevious: + return Argument{ "uninstall-previous"_liv, NoAlias, Args::Type::UninstallPrevious, Resource::String::UninstallPreviousArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::UninstallPreviousArgument }; case Args::Type::Force: return Argument{ "force"_liv, NoAlias, Args::Type::Force, Resource::String::ForceArgumentDescription, ArgumentType::Flag, false }; default: diff --git a/src/AppInstallerCLICore/Commands/InstallCommand.cpp b/src/AppInstallerCLICore/Commands/InstallCommand.cpp index 728b18ad8e..5334b59d17 100644 --- a/src/AppInstallerCLICore/Commands/InstallCommand.cpp +++ b/src/AppInstallerCLICore/Commands/InstallCommand.cpp @@ -47,6 +47,7 @@ namespace AppInstaller::CLI Argument::ForType(Args::Type::CustomHeader), Argument::ForType(Args::Type::AcceptSourceAgreements), Argument::ForType(Args::Type::Rename), + Argument::ForType(Args::Type::UninstallPrevious), Argument::ForType(Args::Type::Force), }; } diff --git a/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp b/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp index 0a804bdf30..d5e64a3cf1 100644 --- a/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp +++ b/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp @@ -107,6 +107,7 @@ namespace AppInstaller::CLI Argument::ForType(Execution::Args::Type::CustomHeader), Argument{ "all"_liv, 'r', "recurse"_liv, Args::Type::All, Resource::String::UpdateAllArgumentDescription, ArgumentType::Flag }, Argument{ "include-unknown"_liv, 'u', "unknown"_liv, Args::Type::IncludeUnknown, Resource::String::IncludeUnknownArgumentDescription, ArgumentType::Flag }, + Argument::ForType(Args::Type::UninstallPrevious), Argument::ForType(Args::Type::Force), }; } diff --git a/src/AppInstallerCLICore/ExecutionArgs.h b/src/AppInstallerCLICore/ExecutionArgs.h index d0df99a98f..381297ff5d 100644 --- a/src/AppInstallerCLICore/ExecutionArgs.h +++ b/src/AppInstallerCLICore/ExecutionArgs.h @@ -83,6 +83,7 @@ namespace AppInstaller::CLI::Execution // Upgrade command All, // Used in Update command to update all installed packages to latest IncludeUnknown, // Used in Upgrade command to allow upgrades of packages with unknown versions + UninstallPrevious, // Used in Upgrade command to override the default manifest behavior to UninstallPrevious // Show command ListVersions, // Used in Show command to list all available versions of an app diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h index 1122c02259..8a523ffa79 100644 --- a/src/AppInstallerCLICore/Resources.h +++ b/src/AppInstallerCLICore/Resources.h @@ -408,6 +408,7 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(UninstallFailedWithCode); WINGET_DEFINE_RESOURCE_STRINGID(UninstallFlowStartingPackageUninstall); WINGET_DEFINE_RESOURCE_STRINGID(UninstallFlowUninstallSuccess); + WINGET_DEFINE_RESOURCE_STRINGID(UninstallPreviousArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(UnrecognizedCommand); WINGET_DEFINE_RESOURCE_STRINGID(UnsupportedArgument); WINGET_DEFINE_RESOURCE_STRINGID(UpdateAllArgumentDescription); diff --git a/src/AppInstallerCLICore/Workflows/InstallFlow.cpp b/src/AppInstallerCLICore/Workflows/InstallFlow.cpp index 8b7ded7a6e..31111b3237 100644 --- a/src/AppInstallerCLICore/Workflows/InstallFlow.cpp +++ b/src/AppInstallerCLICore/Workflows/InstallFlow.cpp @@ -257,6 +257,7 @@ namespace AppInstaller::CLI::Workflow { bool isUpdate = WI_IsFlagSet(context.GetFlags(), Execution::ContextFlag::InstallerExecutionUseUpdate); UpdateBehaviorEnum updateBehavior = context.Get().value().UpdateBehavior; + bool doUninstallPrevious = isUpdate && (updateBehavior == UpdateBehaviorEnum::UninstallPrevious || context.Args.Contains(Execution::Args::Type::UninstallPrevious)); switch (m_installerType) { @@ -266,7 +267,7 @@ namespace AppInstaller::CLI::Workflow case InstallerTypeEnum::Msi: case InstallerTypeEnum::Nullsoft: case InstallerTypeEnum::Wix: - if (isUpdate && updateBehavior == UpdateBehaviorEnum::UninstallPrevious) + if (doUninstallPrevious) { context << GetUninstallInfo << @@ -291,7 +292,7 @@ namespace AppInstaller::CLI::Workflow (isUpdate ? MSStoreUpdate : MSStoreInstall); break; case InstallerTypeEnum::Portable: - if (isUpdate && updateBehavior == UpdateBehaviorEnum::UninstallPrevious) + if (doUninstallPrevious) { context << GetUninstallInfo << diff --git a/src/AppInstallerCLIE2ETests/BaseCommand.cs b/src/AppInstallerCLIE2ETests/BaseCommand.cs index 4e53ae17ce..dfd64381ee 100644 --- a/src/AppInstallerCLIE2ETests/BaseCommand.cs +++ b/src/AppInstallerCLIE2ETests/BaseCommand.cs @@ -87,6 +87,7 @@ public void InitializeAllFeatures(bool status) this.ConfigureFeature("directMSI", status); this.ConfigureFeature("zipInstall", status); this.ConfigureFeature("openLogsArgument", status); + this.ConfigureFeature("uninstallPreviousArgument", status); } } } diff --git a/src/AppInstallerCLIE2ETests/FeaturesCommand.cs b/src/AppInstallerCLIE2ETests/FeaturesCommand.cs index b7bc77060d..8fc65b553f 100644 --- a/src/AppInstallerCLIE2ETests/FeaturesCommand.cs +++ b/src/AppInstallerCLIE2ETests/FeaturesCommand.cs @@ -53,6 +53,7 @@ public void EnableExperimentalFeatures() this.ConfigureFeature("experimentalCmd", true); this.ConfigureFeature("directMSI", true); this.ConfigureFeature("openLogsArgument", true); + this.ConfigureFeature("uninstallPreviousArgument", true); var result = TestCommon.RunAICLICommand("features", string.Empty); Assert.True(result.StdOut.Contains("Enabled")); } diff --git a/src/AppInstallerCLIE2ETests/SetUpFixture.cs b/src/AppInstallerCLIE2ETests/SetUpFixture.cs index 43a28e49f2..9227d14d7c 100644 --- a/src/AppInstallerCLIE2ETests/SetUpFixture.cs +++ b/src/AppInstallerCLIE2ETests/SetUpFixture.cs @@ -158,6 +158,7 @@ public void InitializeWingetSettings() dependencies = false, directMSI = false, openLogsArgument = false, + uninstallPreviousArgument = false, }, debugging = new { diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index 73044e944f..6a2325bcae 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -663,6 +663,9 @@ They can be configured through the settings file 'winget settings'. An unexpected error occurred while executing the command: + + Uninstall the previous version of the package during upgrade + Unrecognized command diff --git a/src/AppInstallerCommonCore/ExperimentalFeature.cpp b/src/AppInstallerCommonCore/ExperimentalFeature.cpp index 22bcec667a..6dddaede20 100644 --- a/src/AppInstallerCommonCore/ExperimentalFeature.cpp +++ b/src/AppInstallerCommonCore/ExperimentalFeature.cpp @@ -48,6 +48,8 @@ namespace AppInstaller::Settings return userSettings.Get(); case ExperimentalFeature::Feature::Pinning: return userSettings.Get(); + case ExperimentalFeature::Feature::UninstallPreviousArgument: + return userSettings.Get(); default: THROW_HR(E_UNEXPECTED); } @@ -85,6 +87,8 @@ namespace AppInstaller::Settings return ExperimentalFeature{ "Open Logs Argument", "openLogsArgument", "https://aka.ms/winget-settings", Feature::OpenLogsArgument }; case Feature::Pinning: return ExperimentalFeature{ "Package Pinning", "pinning", "https://aka.ms/winget-settings", Feature::Pinning}; + case Feature::UninstallPreviousArgument: + return ExperimentalFeature{ "Uninstall Previous Argument", "uninstallPreviousArgument", "https://aka.ms/winget-settings", Feature::UninstallPreviousArgument }; default: THROW_HR(E_UNEXPECTED); } diff --git a/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h b/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h index f34b24d2c3..62c79a2df0 100644 --- a/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h +++ b/src/AppInstallerCommonCore/Public/winget/ExperimentalFeature.h @@ -26,6 +26,7 @@ namespace AppInstaller::Settings ZipInstall = 0x4, OpenLogsArgument = 0x8, Pinning = 0x10, + UninstallPreviousArgument = 0x20, Max, // This MUST always be after all experimental features // Features listed after Max will not be shown with the features command diff --git a/src/AppInstallerCommonCore/Public/winget/UserSettings.h b/src/AppInstallerCommonCore/Public/winget/UserSettings.h index ec14844426..c8ada521b8 100644 --- a/src/AppInstallerCommonCore/Public/winget/UserSettings.h +++ b/src/AppInstallerCommonCore/Public/winget/UserSettings.h @@ -80,6 +80,7 @@ namespace AppInstaller::Settings EFZipInstall, EFOpenLogsArgument, EFPinning, + EFUninstallPreviousArgument, // Telemetry TelemetryDisable, // Install behavior @@ -150,6 +151,7 @@ namespace AppInstaller::Settings SETTINGMAPPING_SPECIALIZATION(Setting::EFZipInstall, bool, bool, false, ".experimentalFeatures.zipInstall"sv); SETTINGMAPPING_SPECIALIZATION(Setting::EFOpenLogsArgument, bool, bool, false, ".experimentalFeatures.openLogsArgument"sv); SETTINGMAPPING_SPECIALIZATION(Setting::EFPinning, bool, bool, false, ".experimentalFeatures.pinning"sv); + SETTINGMAPPING_SPECIALIZATION(Setting::EFUninstallPreviousArgument, bool, bool, false, ".experimentalFeatures.uninstallPreviousArgument"sv); // Telemetry SETTINGMAPPING_SPECIALIZATION(Setting::TelemetryDisable, bool, bool, false, ".telemetry.disable"sv); // Install behavior diff --git a/src/AppInstallerCommonCore/UserSettings.cpp b/src/AppInstallerCommonCore/UserSettings.cpp index c97d086868..866e602098 100644 --- a/src/AppInstallerCommonCore/UserSettings.cpp +++ b/src/AppInstallerCommonCore/UserSettings.cpp @@ -250,6 +250,7 @@ namespace AppInstaller::Settings WINGET_VALIDATE_PASS_THROUGH(EFZipInstall) WINGET_VALIDATE_PASS_THROUGH(EFOpenLogsArgument) WINGET_VALIDATE_PASS_THROUGH(EFPinning) + WINGET_VALIDATE_PASS_THROUGH(EFUninstallPreviousArgument) WINGET_VALIDATE_PASS_THROUGH(TelemetryDisable) WINGET_VALIDATE_PASS_THROUGH(InteractivityDisable) WINGET_VALIDATE_PASS_THROUGH(EnableSelfInitiatedMinidump) From 6cb58a5351fd7c1195f2f71ca85ce2e0dda1f7a9 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Wed, 7 Dec 2022 13:31:38 -0600 Subject: [PATCH 2/2] Fix setting description --- doc/Settings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Settings.md b/doc/Settings.md index 3bbbabf775..cc912e05f9 100644 --- a/doc/Settings.md +++ b/doc/Settings.md @@ -256,7 +256,7 @@ You can enable the feature as shown below. ### uninstallPreviousArgument -This feature enables the Windows Package Manager to override the upgrade behavior to UninstallPrevious by passing the `--uninstall-previous` argument with any command. +This feature enables the Windows Package Manager to override the upgrade behavior to UninstallPrevious by passing the `--uninstall-previous` argument with the upgrade or install command. You can enable the feature as shown below. ```json