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/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 fc5281d36b..e7523e92c7 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 1e66baf7c3..380c62b227 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/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/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/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/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h index 335751e5e9..6d95441a40 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/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 a23bc4260d..9586c7950b 100644 --- a/src/AppInstallerCLIE2ETests/Constants.cs +++ b/src/AppInstallerCLIE2ETests/Constants.cs @@ -130,6 +130,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/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index d4d668f0a1..62b0ca25fa 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -3183,6 +3183,10 @@ Please specify one of them using the --source option to proceed. Version + + Configuration Modules + PowerShell Modules that are used for the Configuration feature + Install a font 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/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"); 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")); 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) { 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/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/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: 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"; 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 +} 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" }