From f97417f2ea850757d0a3337be877ac35f371a9ea Mon Sep 17 00:00:00 2001 From: Ryan <69221034+ryfu-msft@users.noreply.github.com> Date: Tue, 26 Nov 2024 15:40:30 -0500 Subject: [PATCH 1/7] Add default module root setting for configuration (#4974) --- doc/Settings.md | 15 +++++++++++ .../JSON/settings/settings.schema.0.2.json | 11 ++++++++ .../ConfigurationCommon.cpp | 11 ++++++-- .../ConfigureCommand.cs | 25 +++++++++++++++++++ src/AppInstallerCLIE2ETests/Constants.cs | 1 + src/AppInstallerCLIE2ETests/ErrorCommand.cs | 13 ++++++++-- .../Helpers/WinGetSettingsHelper.cs | 20 +++++++++++++++ src/AppInstallerCLITests/UserSettings.cpp | 15 +++++++++++ .../Public/winget/UserSettings.h | 4 +++ src/AppInstallerCommonCore/UserSettings.cpp | 5 ++++ 10 files changed, 116 insertions(+), 4 deletions(-) diff --git a/doc/Settings.md b/doc/Settings.md index f593fc946f..027c0066ab 100644 --- a/doc/Settings.md +++ b/doc/Settings.md @@ -200,6 +200,21 @@ The `purgePortablePackage` behavior affects the default behavior for uninstallin }, ``` +## Configure Behavior + +The `configureBehavior` settings affect the default behavior of applying a configuration. + +### Default Module Root +The `defaultModuleRoot` behavior affects the default root directory where modules are installed to. Defaults to `%LOCALAPPDATA%/Microsoft/WinGet/Configuration/Modules` if value is not set or is invalid. + +> Note: This setting value must be an absolute path. + +```json + "configureBehavior": { + "defaultModuleRoot": "C:/Program Files/Modules/" + }, +``` + ## Telemetry The `telemetry` settings control whether winget writes ETW events that may be sent to Microsoft on a default installation of Windows. diff --git a/schemas/JSON/settings/settings.schema.0.2.json b/schemas/JSON/settings/settings.schema.0.2.json index 2113127f0e..099ebe8080 100644 --- a/schemas/JSON/settings/settings.schema.0.2.json +++ b/schemas/JSON/settings/settings.schema.0.2.json @@ -198,6 +198,17 @@ } } }, + "ConfigureBehavior": { + "description": "Configure settings", + "type": "object", + "properties": { + "defaultModuleRoot": { + "description": "The default root directory where PowerShell modules are installed to when applying a configuration.", + "type": "string", + "maxLength": 32767 + } + } + }, "DownloadBehavior": { "description": "Download settings", "type": "object", diff --git a/src/AppInstallerCLICore/ConfigurationCommon.cpp b/src/AppInstallerCLICore/ConfigurationCommon.cpp index c0ba7ef164..7111757493 100644 --- a/src/AppInstallerCLICore/ConfigurationCommon.cpp +++ b/src/AppInstallerCLICore/ConfigurationCommon.cpp @@ -21,7 +21,7 @@ namespace AppInstaller::CLI struct ModulePathInfo { SetProcessorFactory::PwshConfigurationProcessorLocation location; - std::optional customLocation; + std::optional customLocation; }; ModulePathInfo GetModulePathInfo(Execution::Args& execArgs) @@ -44,10 +44,17 @@ namespace AppInstaller::CLI } else { - return { SetProcessorFactory::PwshConfigurationProcessorLocation::Custom, execArgs.GetArg(Execution::Args::Type::ConfigurationModulePath) }; + return { SetProcessorFactory::PwshConfigurationProcessorLocation::Custom, std::string(execArgs.GetArg(Execution::Args::Type::ConfigurationModulePath)) }; } } + std::filesystem::path defaultModuleRoot = Settings::User().Get(); + + if (!defaultModuleRoot.empty()) + { + return { SetProcessorFactory::PwshConfigurationProcessorLocation::Custom, defaultModuleRoot.u8string() }; + } + return { SetProcessorFactory::PwshConfigurationProcessorLocation::WinGetModulePath, {} }; } } diff --git a/src/AppInstallerCLIE2ETests/ConfigureCommand.cs b/src/AppInstallerCLIE2ETests/ConfigureCommand.cs index f296b68df0..ae8a2b0a90 100644 --- a/src/AppInstallerCLIE2ETests/ConfigureCommand.cs +++ b/src/AppInstallerCLIE2ETests/ConfigureCommand.cs @@ -76,6 +76,31 @@ public void ConfigureFromTestRepo() Constants.SimpleTestModuleName))); } + /// + /// Simple test to confirm that the module was installed to the location specified in the DefaultModuleRoot settings. + /// + [Test] + public void ConfigureFromTestRepo_DefaultModuleRootSetting() + { + TestCommon.EnsureModuleState(Constants.SimpleTestModuleName, present: false); + string moduleTestDir = TestCommon.GetRandomTestDir(); + WinGetSettingsHelper.ConfigureConfigureBehavior(Constants.DefaultModuleRoot, moduleTestDir); + + string args = TestCommon.GetTestDataFile("Configuration\\Configure_TestRepo_Location.yml"); + var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, args); + + WinGetSettingsHelper.ConfigureConfigureBehavior(Constants.DefaultModuleRoot, string.Empty); + bool moduleExists = Directory.Exists(Path.Combine(moduleTestDir, Constants.SimpleTestModuleName)); + if (moduleExists) + { + // Clean test directory to avoid impacting other tests. + Directory.Delete(moduleTestDir, true); + } + + Assert.AreEqual(0, result.ExitCode); + Assert.True(moduleExists); + } + /// /// Simple test to confirm that the module was installed in the right location. /// diff --git a/src/AppInstallerCLIE2ETests/Constants.cs b/src/AppInstallerCLIE2ETests/Constants.cs index 25fcb6d72c..70d3023a18 100644 --- a/src/AppInstallerCLIE2ETests/Constants.cs +++ b/src/AppInstallerCLIE2ETests/Constants.cs @@ -125,6 +125,7 @@ public class Constants public const string PortablePackageMachineRoot = "portablePackageMachineRoot"; public const string InstallBehaviorScope = "scope"; public const string InstallerTypes = "installerTypes"; + public const string DefaultModuleRoot = "defaultModuleRoot"; // Configuration public const string PSGalleryName = "PSGallery"; diff --git a/src/AppInstallerCLIE2ETests/ErrorCommand.cs b/src/AppInstallerCLIE2ETests/ErrorCommand.cs index 8bc67d6b76..10a257defe 100644 --- a/src/AppInstallerCLIE2ETests/ErrorCommand.cs +++ b/src/AppInstallerCLIE2ETests/ErrorCommand.cs @@ -1,4 +1,4 @@ -// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. Licensed under the MIT License. // @@ -14,6 +14,15 @@ namespace AppInstallerCLIE2ETests /// public class ErrorCommand { + /// + /// Reset settings file to avoid affecting output from error command. + /// + [OneTimeSetUp] + public void OneTimeSetup() + { + WinGetSettingsHelper.InitializeWingetSettings(); + } + /// /// Tests 0. /// @@ -127,4 +136,4 @@ public void String() Assert.True(result.StdOut.Contains("APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE")); } } -} \ No newline at end of file +} diff --git a/src/AppInstallerCLIE2ETests/Helpers/WinGetSettingsHelper.cs b/src/AppInstallerCLIE2ETests/Helpers/WinGetSettingsHelper.cs index 0a5e2cf069..703d177b5e 100644 --- a/src/AppInstallerCLIE2ETests/Helpers/WinGetSettingsHelper.cs +++ b/src/AppInstallerCLIE2ETests/Helpers/WinGetSettingsHelper.cs @@ -73,6 +73,12 @@ public static void InitializeWingetSettings() { } }, + { + "configureBehavior", + new Hashtable() + { + } + }, }; // Run winget one time to initialize settings directory @@ -108,6 +114,20 @@ public static void ConfigureInstallBehavior(string settingName, string value) SetWingetSettings(settingsJson); } + /// + /// Configure the configuration behavior. + /// + /// Setting name. + /// Setting value. + public static void ConfigureConfigureBehavior(string settingName, string value) + { + JObject settingsJson = GetJsonSettingsObject("configureBehavior"); + var configureBehavior = settingsJson["configureBehavior"]; + configureBehavior[settingName] = value; + + SetWingetSettings(settingsJson); + } + /// /// Configure the install behavior preferences. /// diff --git a/src/AppInstallerCLITests/UserSettings.cpp b/src/AppInstallerCLITests/UserSettings.cpp index ed54c36bbc..3d0820f8d5 100644 --- a/src/AppInstallerCLITests/UserSettings.cpp +++ b/src/AppInstallerCLITests/UserSettings.cpp @@ -526,6 +526,21 @@ TEST_CASE("SettingsDownloadDefaultDirectory", "[settings]") } } +TEST_CASE("SettingsConfigureDefaultModuleRoot", "[settings]") +{ + auto again = DeleteUserSettingsFiles(); + + SECTION("Valid path") + { + std::string_view json = R"({ "configureBehavior": { "defaultModuleRoot": "C:/Foo/Bar" } })"; + SetSetting(Stream::PrimaryUserSettings, json); + UserSettingsTest userSettingTest; + + REQUIRE(userSettingTest.Get() == "C:/Foo/Bar"); + REQUIRE(userSettingTest.GetWarnings().size() == 0); + } +} + TEST_CASE("SettingsArchiveExtractionMethod", "[settings]") { auto again = DeleteUserSettingsFiles(); diff --git a/src/AppInstallerCommonCore/Public/winget/UserSettings.h b/src/AppInstallerCommonCore/Public/winget/UserSettings.h index b580775c28..d13d3e8f46 100644 --- a/src/AppInstallerCommonCore/Public/winget/UserSettings.h +++ b/src/AppInstallerCommonCore/Public/winget/UserSettings.h @@ -108,6 +108,8 @@ namespace AppInstaller::Settings UninstallPurgePortablePackage, // Download behavior DownloadDefaultDirectory, + // Configure behavior + ConfigureDefaultModuleRoot, // Interactivity InteractivityDisable, #ifndef AICLI_DISABLE_TEST_HOOKS @@ -185,6 +187,8 @@ namespace AppInstaller::Settings SETTINGMAPPING_SPECIALIZATION(Setting::UninstallPurgePortablePackage, bool, bool, false, ".uninstallBehavior.purgePortablePackage"sv); // Download behavior SETTINGMAPPING_SPECIALIZATION(Setting::DownloadDefaultDirectory, std::string, std::filesystem::path, {}, ".downloadBehavior.defaultDownloadDirectory"sv); + // Configure behavior + SETTINGMAPPING_SPECIALIZATION(Setting::ConfigureDefaultModuleRoot, std::string, std::filesystem::path, {}, ".configureBehavior.defaultModuleRoot"sv); // Network SETTINGMAPPING_SPECIALIZATION(Setting::NetworkDownloader, std::string, InstallerDownloader, InstallerDownloader::Default, ".network.downloader"sv); diff --git a/src/AppInstallerCommonCore/UserSettings.cpp b/src/AppInstallerCommonCore/UserSettings.cpp index 9e13610537..d6879e9b9a 100644 --- a/src/AppInstallerCommonCore/UserSettings.cpp +++ b/src/AppInstallerCommonCore/UserSettings.cpp @@ -401,6 +401,11 @@ namespace AppInstaller::Settings return ValidatePathValue(value); } + WINGET_VALIDATE_SIGNATURE(ConfigureDefaultModuleRoot) + { + return ValidatePathValue(value); + } + WINGET_VALIDATE_SIGNATURE(NetworkDownloader) { static constexpr std::string_view s_downloader_default = "default"; From e0c43c4047096977d49a3338e49d6682c34067cd Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Mon, 2 Dec 2024 15:44:55 -0600 Subject: [PATCH 2/7] Add tests for ensuring integers are parsed correctly with leading zeroes (#5013) - [x] I have signed the [Contributor License Agreement](https://cla.opensource.microsoft.com/microsoft/winget-pkgs). - [ ] This pull request is related to an issue. I wasn't sure offhand if these versions would parse to be equal. I went to look at the test cases and found there were no tests that ensured that leading zeroes were parsed correctly. This PR adds the tests for clarity ----- ###### Microsoft Reviewers: [Open in CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/microsoft/winget-cli/pull/5013) --- src/AppInstallerCLITests/Versions.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/AppInstallerCLITests/Versions.cpp b/src/AppInstallerCLITests/Versions.cpp index 5a05be6db1..38e0dcc1b9 100644 --- a/src/AppInstallerCLITests/Versions.cpp +++ b/src/AppInstallerCLITests/Versions.cpp @@ -170,9 +170,16 @@ TEST_CASE("VersionCompare", "[versions]") RequireEqual("1.0", "1.0.0"); + // Ensure that integers are parsed correctly when there is a leading zero + RequireEqual("1.2.00.3", "1.2.0.3"); + RequireEqual("1.2.003.4", "1.2.3.4"); + RequireEqual("01.02.03.04", "1.2.3.4"); + RequireEqual("1.2.03-beta", "1.2.3-beta"); + // Ensure whitespace doesn't affect equality RequireEqual("1.0", "1.0 "); RequireEqual("1.0", "1. 0"); + RequireEqual("1.0", "1.0."); // Ensure versions with preambles are sorted correctly RequireEqual("1.0", "Version 1.0"); From 4ad9e4035e68a6a043f9fb7b2c74ed3fa9e9fa0e Mon Sep 17 00:00:00 2001 From: Ryan <69221034+ryfu-msft@users.noreply.github.com> Date: Tue, 3 Dec 2024 19:14:09 -0500 Subject: [PATCH 3/7] Update description for 1.10 schema (#5014) --- .../manifest.defaultLocale.1.10.0.json | 4 +-- .../v1.10.0/manifest.installer.1.10.0.json | 4 +-- .../v1.10.0/manifest.locale.1.10.0.json | 4 +-- .../v1.10.0/manifest.singleton.1.10.0.json | 4 +-- .../v1.10.0/manifest.version.1.10.0.json | 4 +-- src/AppInstallerCLITests/YamlManifest.cpp | 31 +++++++++++++++++++ 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/schemas/JSON/manifests/v1.10.0/manifest.defaultLocale.1.10.0.json b/schemas/JSON/manifests/v1.10.0/manifest.defaultLocale.1.10.0.json index c1be7ab447..2713d87b71 100644 --- a/schemas/JSON/manifests/v1.10.0/manifest.defaultLocale.1.10.0.json +++ b/schemas/JSON/manifests/v1.10.0/manifest.defaultLocale.1.10.0.json @@ -1,7 +1,7 @@ { - "$id": "https://aka.ms/winget-manifest.defaultlocale.1.9.0.schema.json", + "$id": "https://aka.ms/winget-manifest.defaultlocale.1.10.0.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", - "description": "A representation of a multiple-file manifest representing a default app metadata in the OWC. v1.9.0", + "description": "A representation of a multiple-file manifest representing a default app metadata in the OWC. v1.10.0", "definitions": { "Url": { "type": [ "string", "null" ], diff --git a/schemas/JSON/manifests/v1.10.0/manifest.installer.1.10.0.json b/schemas/JSON/manifests/v1.10.0/manifest.installer.1.10.0.json index c64358a9e0..98da3b2c34 100644 --- a/schemas/JSON/manifests/v1.10.0/manifest.installer.1.10.0.json +++ b/schemas/JSON/manifests/v1.10.0/manifest.installer.1.10.0.json @@ -1,7 +1,7 @@ { - "$id": "https://aka.ms/winget-manifest.installer.1.9.0.schema.json", + "$id": "https://aka.ms/winget-manifest.installer.1.10.0.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", - "description": "A representation of a single-file manifest representing an app installers in the OWC. v1.9.0", + "description": "A representation of a single-file manifest representing an app installers in the OWC. v1.10.0", "definitions": { "PackageIdentifier": { "type": "string", diff --git a/schemas/JSON/manifests/v1.10.0/manifest.locale.1.10.0.json b/schemas/JSON/manifests/v1.10.0/manifest.locale.1.10.0.json index 98e28826dd..35e7db70fc 100644 --- a/schemas/JSON/manifests/v1.10.0/manifest.locale.1.10.0.json +++ b/schemas/JSON/manifests/v1.10.0/manifest.locale.1.10.0.json @@ -1,7 +1,7 @@ { - "$id": "https://aka.ms/winget-manifest.locale.1.9.0.schema.json", + "$id": "https://aka.ms/winget-manifest.locale.1.10.0.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", - "description": "A representation of a multiple-file manifest representing app metadata in other locale in the OWC. v1.9.0", + "description": "A representation of a multiple-file manifest representing app metadata in other locale in the OWC. v1.10.0", "definitions": { "Url": { "type": [ "string", "null" ], diff --git a/schemas/JSON/manifests/v1.10.0/manifest.singleton.1.10.0.json b/schemas/JSON/manifests/v1.10.0/manifest.singleton.1.10.0.json index 084bafedd5..dd48208c79 100644 --- a/schemas/JSON/manifests/v1.10.0/manifest.singleton.1.10.0.json +++ b/schemas/JSON/manifests/v1.10.0/manifest.singleton.1.10.0.json @@ -1,7 +1,7 @@ { - "$id": "https://aka.ms/winget-manifest.singleton.1.9.0.schema.json", + "$id": "https://aka.ms/winget-manifest.singleton.1.10.0.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", - "description": "A representation of a single-file manifest representing an app in the OWC. v1.9.0", + "description": "A representation of a single-file manifest representing an app in the OWC. v1.10.0", "definitions": { "PackageIdentifier": { "type": "string", diff --git a/schemas/JSON/manifests/v1.10.0/manifest.version.1.10.0.json b/schemas/JSON/manifests/v1.10.0/manifest.version.1.10.0.json index a57172911e..c682e28122 100644 --- a/schemas/JSON/manifests/v1.10.0/manifest.version.1.10.0.json +++ b/schemas/JSON/manifests/v1.10.0/manifest.version.1.10.0.json @@ -1,7 +1,7 @@ { - "$id": "https://aka.ms/winget-manifest.version.1.9.0.schema.json", + "$id": "https://aka.ms/winget-manifest.version.1.10.0.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", - "description": "A representation of a multi-file manifest representing an app version in the OWC. v1.9.0", + "description": "A representation of a multi-file manifest representing an app version in the OWC. v1.10.0", "type": "object", "properties": { "PackageIdentifier": { diff --git a/src/AppInstallerCLITests/YamlManifest.cpp b/src/AppInstallerCLITests/YamlManifest.cpp index d402596424..65144a8d43 100644 --- a/src/AppInstallerCLITests/YamlManifest.cpp +++ b/src/AppInstallerCLITests/YamlManifest.cpp @@ -1386,6 +1386,37 @@ TEST_CASE("WriteV1_9SingletonManifestAndVerifyContents", "[ManifestCreation]") VerifyV1ManifestContent(generatedMultiFileManifest, false, ManifestVer{ s_ManifestVersionV1_9 }, true); } +TEST_CASE("WriteV1_10SingletonManifestAndVerifyContents", "[ManifestCreation]") +{ + TempDirectory singletonDirectory{ "SingletonManifest" }; + CopyTestDataFilesToFolder({ "ManifestV1_10-Singleton.yaml" }, singletonDirectory); + Manifest singletonManifest = YamlParser::CreateFromPath(singletonDirectory); + + TempDirectory exportedSingletonDirectory{ "exportedSingleton" }; + std::filesystem::path generatedSingletonManifestPath = exportedSingletonDirectory.GetPath() / "testSingletonManifest.yaml"; + YamlWriter::OutputYamlFile(singletonManifest, singletonManifest.Installers[0], generatedSingletonManifestPath); + + REQUIRE(std::filesystem::exists(generatedSingletonManifestPath)); + Manifest generatedSingletonManifest = YamlParser::CreateFromPath(exportedSingletonDirectory); + VerifyV1ManifestContent(generatedSingletonManifest, true, ManifestVer{ s_ManifestVersionV1_10 }, true); + + TempDirectory multiFileDirectory{ "MultiFileManifest" }; + CopyTestDataFilesToFolder({ + "ManifestV1_10-MultiFile-Version.yaml", + "ManifestV1_10-MultiFile-Installer.yaml", + "ManifestV1_10-MultiFile-DefaultLocale.yaml", + "ManifestV1_10-MultiFile-Locale.yaml" }, multiFileDirectory); + + Manifest multiFileManifest = YamlParser::CreateFromPath(multiFileDirectory); + TempDirectory exportedMultiFileDirectory{ "exportedMultiFile" }; + std::filesystem::path generatedMultiFileManifestPath = exportedMultiFileDirectory.GetPath() / "testMultiFileManifest.yaml"; + YamlWriter::OutputYamlFile(multiFileManifest, multiFileManifest.Installers[0], generatedMultiFileManifestPath); + + REQUIRE(std::filesystem::exists(generatedMultiFileManifestPath)); + Manifest generatedMultiFileManifest = YamlParser::CreateFromPath(exportedMultiFileDirectory); + VerifyV1ManifestContent(generatedMultiFileManifest, false, ManifestVer{ s_ManifestVersionV1_10 }, true); +} + TEST_CASE("WriteManifestWithMultipleLocale", "[ManifestCreation]") { Manifest multiLocaleManifest = YamlParser::CreateFromPath(TestDataFile("Manifest-Good-MultiLocale.yaml")); From a54bbbe047d3b3eac54c9d7668827864afce0a9b Mon Sep 17 00:00:00 2001 From: yao-msft <50888816+yao-msft@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:58:12 -0800 Subject: [PATCH 4/7] Add missing ReturnResponseUrl to WinGetUtilInterop manifest (#5035) --- .../ManifestUnitTest/V1ManifestReadTest.cs | 4 ++++ .../TestCollateral/V1_1ManifestMerged.yaml | 1 - .../TestCollateral/V1_6ManifestMerged.yaml | 11 ++++++----- .../TestCollateral/V1_7ManifestMerged.yaml | 11 ++++++----- .../TestCollateral/V1_9ManifestMerged.yaml | 9 +++++---- .../Manifest/V1/InstallerExpectedReturnCode.cs | 11 ++++++++--- 6 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs index ecff759994..72f24a5272 100644 --- a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs +++ b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs @@ -264,6 +264,8 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif Assert.True(manifest.DisplayInstallWarnings); Assert.True(manifest.DownloadCommandProhibited); + + Assert.Equal("https://defaultReturnResponseUrl.com", manifest.ExpectedReturnCodes[0].ReturnResponseUrl); } if (manifestVersion >= TestManifestVersion.V170) @@ -373,6 +375,8 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif Assert.True(installer1.DisplayInstallWarnings); Assert.True(installer1.DownloadCommandProhibited); + + Assert.Equal("https://returnResponseUrl.com", installer1.ExpectedReturnCodes[0].ReturnResponseUrl); } if (manifestVersion >= TestManifestVersion.V170) diff --git a/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_1ManifestMerged.yaml b/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_1ManifestMerged.yaml index de6888aa7b..eaf2be893d 100644 --- a/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_1ManifestMerged.yaml +++ b/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_1ManifestMerged.yaml @@ -34,7 +34,6 @@ ExpectedReturnCodes: ReturnResponse: contactSupport - InstallerReturnCode: 3 ReturnResponse: custom - ReturnResponseUrl: https://defaultReturnResponseUrl.com FileExtensions: - appx - msix diff --git a/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_6ManifestMerged.yaml b/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_6ManifestMerged.yaml index 60769f3d8d..1eb70ac0ab 100644 --- a/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_6ManifestMerged.yaml +++ b/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_6ManifestMerged.yaml @@ -105,10 +105,10 @@ Markets: - US ExpectedReturnCodes: - InstallerReturnCode: 2 - ReturnResponse: contactSupport + ReturnResponse: contactSupport + ReturnResponseUrl: https://defaultReturnResponseUrl.com - InstallerReturnCode: 3 ReturnResponse: custom - ReturnResponseUrl: https://defaultReturnResponseUrl.com UnsupportedArguments: - log NestedInstallerType: msi @@ -225,8 +225,9 @@ Installers: ExcludedMarkets: - "US" ExpectedReturnCodes: - - InstallerReturnCode: 2 - ReturnResponse: contactSupport + - InstallerReturnCode: 2 + ReturnResponse: contactSupport + ReturnResponseUrl: https://returnResponseUrl.com DownloadCommandProhibited: true InstallationMetadata: DefaultInstallLocation: "%ProgramFiles%\\TestApp" @@ -242,4 +243,4 @@ Installers: InstallerType: exe ProductCode: '{Bar}' ManifestType: merged -ManifestVersion: 1.6.0 \ No newline at end of file +ManifestVersion: 1.6.0 diff --git a/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_7ManifestMerged.yaml b/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_7ManifestMerged.yaml index f6632a15ed..42640d1993 100644 --- a/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_7ManifestMerged.yaml +++ b/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_7ManifestMerged.yaml @@ -106,10 +106,10 @@ Markets: - US ExpectedReturnCodes: - InstallerReturnCode: 2 - ReturnResponse: contactSupport + ReturnResponse: contactSupport + ReturnResponseUrl: https://defaultReturnResponseUrl.com - InstallerReturnCode: 3 ReturnResponse: custom - ReturnResponseUrl: https://defaultReturnResponseUrl.com UnsupportedArguments: - log NestedInstallerType: msi @@ -228,8 +228,9 @@ Installers: ExcludedMarkets: - "US" ExpectedReturnCodes: - - InstallerReturnCode: 2 - ReturnResponse: contactSupport + - InstallerReturnCode: 2 + ReturnResponse: contactSupport + ReturnResponseUrl: https://returnResponseUrl.com DownloadCommandProhibited: true RepairBehavior: modify InstallationMetadata: @@ -246,4 +247,4 @@ Installers: InstallerType: exe ProductCode: '{Bar}' ManifestType: merged -ManifestVersion: 1.7.0 \ No newline at end of file +ManifestVersion: 1.7.0 diff --git a/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_9ManifestMerged.yaml b/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_9ManifestMerged.yaml index 3bf371df37..b6efa0343b 100644 --- a/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_9ManifestMerged.yaml +++ b/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_9ManifestMerged.yaml @@ -106,10 +106,10 @@ Markets: - US ExpectedReturnCodes: - InstallerReturnCode: 2 - ReturnResponse: contactSupport + ReturnResponse: contactSupport + ReturnResponseUrl: https://defaultReturnResponseUrl.com - InstallerReturnCode: 3 ReturnResponse: custom - ReturnResponseUrl: https://defaultReturnResponseUrl.com UnsupportedArguments: - log NestedInstallerType: msi @@ -229,8 +229,9 @@ Installers: ExcludedMarkets: - "US" ExpectedReturnCodes: - - InstallerReturnCode: 2 - ReturnResponse: contactSupport + - InstallerReturnCode: 2 + ReturnResponse: contactSupport + ReturnResponseUrl: https://returnResponseUrl.com DownloadCommandProhibited: true ArchiveBinariesDependOnPath: false RepairBehavior: modify diff --git a/src/WinGetUtilInterop/Manifest/V1/InstallerExpectedReturnCode.cs b/src/WinGetUtilInterop/Manifest/V1/InstallerExpectedReturnCode.cs index 288d8b0b24..56d543521f 100644 --- a/src/WinGetUtilInterop/Manifest/V1/InstallerExpectedReturnCode.cs +++ b/src/WinGetUtilInterop/Manifest/V1/InstallerExpectedReturnCode.cs @@ -1,4 +1,4 @@ -// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. Licensed under the MIT License. // @@ -19,6 +19,11 @@ public class InstallerExpectedReturnCode /// /// Gets or sets the corresponding response category. /// - public string ReturnResponse { get; set; } + public string ReturnResponse { get; set; } + + /// + /// Gets or sets the corresponding response url. + /// + public string ReturnResponseUrl { get; set; } } -} \ No newline at end of file +} From b6bbc658987eb339987ccb8dea4d6f26880e2b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Flor=20Chac=C3=B3n?= <14323496+florelis@users.noreply.github.com> Date: Mon, 9 Dec 2024 14:33:19 -0800 Subject: [PATCH 5/7] Update curl dependency due to CVE-2024-9681 (#4960) See https://curl.se/docs/CVE-2024-9681.html ###### Microsoft Reviewers: [Open in CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/microsoft/winget-cli/pull/4960) --- src/vcpkg.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vcpkg.json b/src/vcpkg.json index 677d3b2388..e7d34a4f5d 100644 --- a/src/vcpkg.json +++ b/src/vcpkg.json @@ -22,7 +22,7 @@ }, { "name": "curl", - "version": "8.10.1" + "version": "8.11.0" }, { "name": "nlohmann-json", @@ -38,5 +38,5 @@ "./VcpkgCustomTriplets" ] }, - "builtin-baseline": "f176b58f35a75f9f8f54099cd9df97d2e2793a2e" + "builtin-baseline": "b2cb0da531c2f1f740045bfe7c4dac59f0b2b69c" } From 09a98081f1b291d0655cba2b8e52cd025cd65b21 Mon Sep 17 00:00:00 2001 From: JohnMcPMS Date: Mon, 9 Dec 2024 19:23:23 -0800 Subject: [PATCH 6/7] Change RepairFailure telemetry event to measure (#5050) ## Change Reduce the `RepairFailure` event to a measure. --- src/AppInstallerCommonCore/AppInstallerTelemetry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AppInstallerCommonCore/AppInstallerTelemetry.cpp b/src/AppInstallerCommonCore/AppInstallerTelemetry.cpp index 448e33d52b..589e35ebc7 100644 --- a/src/AppInstallerCommonCore/AppInstallerTelemetry.cpp +++ b/src/AppInstallerCommonCore/AppInstallerTelemetry.cpp @@ -745,7 +745,7 @@ namespace AppInstaller::Logging AICLI_TraceLoggingStringView(type, "Type"), TraceLoggingUInt32(errorCode, "ErrorCode"), TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance), - TraceLoggingKeyword(MICROSOFT_KEYWORD_CRITICAL_DATA)); + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES)); if (m_useSummary) { From df6a13a32a12ea9e28441098d871e56d599a85d9 Mon Sep 17 00:00:00 2001 From: Muhammad Danish Date: Tue, 10 Dec 2024 22:22:36 +0500 Subject: [PATCH 7/7] Add configuration modules path to '--info' (#5023) - [x] I have signed the [Contributor License Agreement](https://cla.opensource.microsoft.com/microsoft/winget-pkgs). - [ ] This pull request is related to an issue. Adds the WinGet configuration modules location to `--info` table ----- ###### Microsoft Reviewers: [Open in CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/microsoft/winget-cli/pull/5023) --- src/AppInstallerCLICore/Commands/RootCommand.cpp | 1 + src/AppInstallerCLICore/Resources.h | 1 + .../Shared/Strings/en-us/winget.resw | 10 +++++++--- .../Public/AppInstallerRuntime.h | 2 ++ src/AppInstallerCommonCore/Runtime.cpp | 13 +++++++++++++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp index 5580efa14a..c2264129e9 100644 --- a/src/AppInstallerCLICore/Commands/RootCommand.cpp +++ b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -154,6 +154,7 @@ namespace AppInstaller::CLI keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableRoot }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRoot, true).u8string() }); keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableRoot86 }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX86, true).u8string() }); keyDirectories.OutputLine({ Resource::LocString{ Resource::String::InstallerDownloads }, Runtime::GetPathTo(Runtime::PathName::UserProfileDownloads, true).u8string() }); + keyDirectories.OutputLine({ Resource::LocString{ Resource::String::ConfigurationModules }, Runtime::GetPathTo(Runtime::PathName::ConfigurationModules, true).u8string() }); keyDirectories.Complete(); context.Reporter.Info() << std::endl; } diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h index 0765d9f0d8..cd56f587c2 100644 --- a/src/AppInstallerCLICore/Resources.h +++ b/src/AppInstallerCLICore/Resources.h @@ -94,6 +94,7 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationModuleNameOnly); WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationModulePath); WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationModulePathArgError); + WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationModules); WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationModuleWithDetails); WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationNotEnabledMessage); WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationNoTestRun); diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index 7897bb985a..c39f9a9aa7 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -1812,7 +1812,7 @@ Please specify one of them using the --source option to proceed. Configuration successfully applied. - + Unit successfully applied. @@ -3147,7 +3147,7 @@ Please specify one of them using the --source option to proceed. Downloaded zero byte installer; ensure that your network connection is working properly. - + Manage fonts @@ -3183,4 +3183,8 @@ Please specify one of them using the --source option to proceed. Version - + + Configuration Modules + PowerShell Modules that are used for the Configuration feature + + \ No newline at end of file diff --git a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h index cecadb24d8..9f9a63cac0 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h @@ -50,6 +50,8 @@ namespace AppInstaller::Runtime SelfPackageRoot, // The location where user downloads are stored. UserProfileDownloads, + // The location where configuration modules are stored. + ConfigurationModules, // The location where checkpoints are stored. CheckpointsLocation, // The location of the CLI executable file. diff --git a/src/AppInstallerCommonCore/Runtime.cpp b/src/AppInstallerCommonCore/Runtime.cpp index 3a8973d8e9..575ad4e5e7 100644 --- a/src/AppInstallerCommonCore/Runtime.cpp +++ b/src/AppInstallerCommonCore/Runtime.cpp @@ -30,6 +30,7 @@ namespace AppInstaller::Runtime constexpr std::string_view s_PortablePackagesDirectory = "Packages"sv; constexpr std::string_view s_LinksDirectory = "Links"sv; constexpr std::string_view s_FontsInstallDirectory = "Microsoft\\Windows\\Fonts"sv; + constexpr std::string_view s_ConfigurationModulesDirectory = "Configuration\\Modules"sv; // Use production CLSIDs as a surrogate for repository location. #if USE_PROD_CLSIDS constexpr std::string_view s_ImageAssetsDirectoryRelative = "Assets\\WinGet"sv; @@ -240,6 +241,16 @@ namespace AppInstaller::Runtime case PathName::FontsMachineInstallLocation: result.Path = GetKnownFolderPath(FOLDERID_Fonts); break; + case PathName::ConfigurationModules: + result.Path = Settings::User().Get(); + if (result.Path.empty()) + { + result.Path = GetKnownFolderPath(FOLDERID_LocalAppData); + result.Path /= s_SecureSettings_Base; + result.Path /= s_ConfigurationModulesDirectory; + } + mayBeInProfilePath = true; + break; default: THROW_HR(E_UNEXPECTED); } @@ -316,6 +327,7 @@ namespace AppInstaller::Runtime case PathName::UserProfileDownloads: case PathName::FontsUserInstallLocation: case PathName::FontsMachineInstallLocation: + case PathName::ConfigurationModules: result = GetPathDetailsCommon(path, forDisplay); break; case PathName::SelfPackageRoot: @@ -422,6 +434,7 @@ namespace AppInstaller::Runtime case PathName::UserProfileDownloads: case PathName::FontsUserInstallLocation: case PathName::FontsMachineInstallLocation: + case PathName::ConfigurationModules: result = GetPathDetailsCommon(path, forDisplay); break; case PathName::SelfPackageRoot: